log4cplus 2.0.8
tls.h
Go to the documentation of this file.
1// -*- C++ -*-
2// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modifica-
5// tion, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
15// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
17// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
19// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
20// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25#ifndef LOG4CPLUS_THREAD_IMPL_TLS_H
26#define LOG4CPLUS_THREAD_IMPL_TLS_H
27
28#include <log4cplus/config.hxx>
29
30#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
31#pragma once
32#endif
33
34#include <new>
35#include <cassert>
36#include <system_error>
37
38#if ! defined (INSIDE_LOG4CPLUS)
39# error "This header must not be be used outside log4cplus' implementation files."
40#endif
41
42#ifdef LOG4CPLUS_USE_PTHREADS
43# include <pthread.h>
44
45#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
47
48#elif defined (LOG4CPLUS_SINGLE_THREADED)
49# include <vector>
50
51#endif
52
53
54namespace log4cplus { namespace thread { namespace impl {
55
56
57typedef void * tls_value_type;
58
59#ifdef LOG4CPLUS_USE_PTHREADS
60typedef pthread_key_t * tls_key_type;
61typedef void (* tls_init_cleanup_func_type)(void *);
62
63#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
64typedef DWORD tls_key_type;
65typedef PFLS_CALLBACK_FUNCTION tls_init_cleanup_func_type;
66
67#elif defined (LOG4CPLUS_SINGLE_THREADED)
68typedef std::size_t tls_key_type;
69typedef void (* tls_init_cleanup_func_type)(void *);
70
71#endif
72
73
74inline tls_key_type tls_init (tls_init_cleanup_func_type);
75inline tls_value_type tls_get_value (tls_key_type);
76inline void tls_set_value (tls_key_type, tls_value_type);
77inline void tls_cleanup (tls_key_type);
78
79
80#if defined (LOG4CPLUS_USE_PTHREADS)
81tls_key_type
82tls_init (tls_init_cleanup_func_type cleanupfunc)
83{
84 pthread_key_t * key = new pthread_key_t;
85 int ret = pthread_key_create (key, cleanupfunc);
86 if (LOG4CPLUS_UNLIKELY (ret != 0))
87 throw std::system_error(ret, std::system_category (),
88 "pthread_key_create() failed");
89 return key;
90}
91
92
94tls_get_value (tls_key_type key)
95{
96 return pthread_getspecific (*key);
97}
98
99
100void
101tls_set_value (tls_key_type key, tls_value_type value)
102{
103 pthread_setspecific(*key, value);
104}
105
106
107void
108tls_cleanup (tls_key_type key)
109{
110 pthread_key_delete (*key);
111 delete key;
112}
113
114
115#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
116tls_key_type
117tls_init (tls_init_cleanup_func_type cleanupfunc)
118{
119 DWORD const slot = FlsAlloc (cleanupfunc);
120 if (LOG4CPLUS_UNLIKELY (slot == FLS_OUT_OF_INDEXES))
121 {
122 DWORD const eno = GetLastError ();
123 throw std::system_error (static_cast<int>(eno),
124 std::system_category (), "FlsAlloc() failed");
125 }
126 return slot;
127}
128
129
130tls_value_type tls_get_value (tls_key_type k)
131{
132 return FlsGetValue (k);
133}
134
135
136void
137tls_set_value (tls_key_type k, tls_value_type value)
138{
139 FlsSetValue (k, value);
140}
141
142
143void
144tls_cleanup (tls_key_type k)
145{
146 FlsFree (k);
147}
148
149
150#elif defined (LOG4CPLUS_SINGLE_THREADED)
151extern std::vector<tls_value_type> * tls_single_threaded_values;
152
153
154tls_key_type
155tls_init (tls_init_cleanup_func_type)
156{
157 if (! tls_single_threaded_values)
158 tls_single_threaded_values = new std::vector<tls_value_type>;
159 tls_key_type key = tls_single_threaded_values->size ();
160 tls_single_threaded_values->resize (key + 1);
161 return key;
162}
163
164
166tls_get_value (tls_key_type k)
167{
168 assert (k < tls_single_threaded_values->size ());
169 return (*tls_single_threaded_values)[k];
170}
171
172
173void
174tls_set_value (tls_key_type k, tls_value_type val)
175{
176 assert (k < tls_single_threaded_values->size ());
177 (*tls_single_threaded_values)[k] = val;
178}
179
180
181void
182tls_cleanup (tls_key_type k)
183{
184 assert (k < tls_single_threaded_values->size ());
185 (*tls_single_threaded_values)[k] = 0;
186}
187
188#endif
189
190
191} } } // namespace log4cplus { namespace thread { namespace impl {
192
193#endif // LOG4CPLUS_THREAD_IMPL_TLS_H
#define LOG4CPLUS_UNLIKELY(cond)
Definition: config.hxx:141
tls_key_type tls_init(tls_init_cleanup_func_type)
void tls_set_value(tls_key_type, tls_value_type)
tls_value_type tls_get_value(tls_key_type)
void * tls_value_type
Definition: tls.h:57
void tls_cleanup(tls_key_type)