log4cplus  2.1.0
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 
54 namespace log4cplus { namespace thread { namespace impl {
55 
56 
57 typedef void * tls_value_type;
58 
59 #ifdef LOG4CPLUS_USE_PTHREADS
60 typedef pthread_key_t * tls_key_type;
61 typedef void (* tls_init_cleanup_func_type)(void *);
62 
63 #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
64 typedef DWORD tls_key_type;
65 typedef PFLS_CALLBACK_FUNCTION tls_init_cleanup_func_type;
66 
67 #elif defined (LOG4CPLUS_SINGLE_THREADED)
68 typedef std::size_t tls_key_type;
69 typedef void (* tls_init_cleanup_func_type)(void *);
70 
71 #endif
72 
73 
74 inline tls_key_type tls_init (tls_init_cleanup_func_type);
75 inline tls_value_type tls_get_value (tls_key_type);
76 inline void tls_set_value (tls_key_type, tls_value_type);
77 inline void tls_cleanup (tls_key_type);
78 
79 
80 #if defined (LOG4CPLUS_USE_PTHREADS)
81 tls_key_type
82 tls_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 
94 tls_get_value (tls_key_type key)
95 {
96  return pthread_getspecific (*key);
97 }
98 
99 
100 void
101 tls_set_value (tls_key_type key, tls_value_type value)
102 {
103  pthread_setspecific(*key, value);
104 }
105 
106 
107 void
108 tls_cleanup (tls_key_type key)
109 {
110  pthread_key_delete (*key);
111  delete key;
112 }
113 
114 
115 #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
116 tls_key_type
117 tls_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 
130 tls_value_type tls_get_value (tls_key_type k)
131 {
132  return FlsGetValue (k);
133 }
134 
135 
136 void
137 tls_set_value (tls_key_type k, tls_value_type value)
138 {
139  FlsSetValue (k, value);
140 }
141 
142 
143 void
144 tls_cleanup (tls_key_type k)
145 {
146  FlsFree (k);
147 }
148 
149 
150 #elif defined (LOG4CPLUS_SINGLE_THREADED)
151 extern std::vector<tls_value_type> * tls_single_threaded_values;
152 
153 
154 tls_key_type
155 tls_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 
166 tls_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 
173 void
174 tls_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 
181 void
182 tls_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)