MongoDB  2.7.0
threadlocal.h
1 #pragma once
2 
32 #include <boost/thread/tss.hpp>
33 #include <boost/bind.hpp>
35 
36 
37 namespace mongo {
38 
39  using boost::thread_specific_ptr;
40 
41  /* thread local "value" rather than a pointer
42  good for things which have copy constructors (and the copy constructor is fast enough)
43  e.g.
44  ThreadLocalValue<int> myint;
45  */
46  template<class T>
48  public:
49  ThreadLocalValue( T def = 0 ) : _default( def ) { }
50 
51  T get() const {
52  T * val = _val.get();
53  if ( val )
54  return *val;
55  return _default;
56  }
57 
58  void set( const T& i ) {
59  T *v = _val.get();
60  if( v ) {
61  *v = i;
62  return;
63  }
64  v = new T(i);
65  _val.reset( v );
66  }
67 
68  T& getRef() {
69  T *v = _val.get();
70  if( v ) {
71  return *v;
72  }
73  v = new T(_default);
74  _val.reset( v );
75  return *v;
76  }
77 
78  private:
79  boost::thread_specific_ptr<T> _val;
80  const T _default;
81  };
82 
83  /* TSP
84  These macros use intrinsics which are faster than boost::thread_specific_ptr.
85  However the intrinsics don't free up objects on thread closure. Thus we use
86  a combination here, with the assumption that reset's are infrequent, so that
87  get's are fast.
88  */
89 #if defined(MONGO_HAVE___THREAD) || defined(MONGO_HAVE___DECLSPEC_THREAD)
90 
91  template< class T >
92  struct TSP {
93  boost::thread_specific_ptr<T> tsp;
94  public:
95  T* get() const;
96  void reset(T* v);
97  T* getMake() {
98  T *t = get();
99  if( t == 0 )
100  reset( t = new T() );
101  return t;
102  }
103  };
104 
105 # if defined(MONGO_HAVE___DECLSPEC_THREAD)
106 
107 # define TSP_DECLARE(T,p) extern TSP<T> p;
108 
109 # define TSP_DEFINE(T,p) __declspec( thread ) T* _ ## p; \
110  TSP<T> p; \
111  template<> T* TSP<T>::get() const { return _ ## p; } \
112  void TSP<T>::reset(T* v) { \
113  tsp.reset(v); \
114  _ ## p = v; \
115  }
116 # else
117 
118 # define TSP_DECLARE(T,p) \
119  extern __thread T* _ ## p; \
120  template<> inline T* TSP<T>::get() const { return _ ## p; } \
121  extern TSP<T> p;
122 
123 # define TSP_DEFINE(T,p) \
124  __thread T* _ ## p; \
125  template<> void TSP<T>::reset(T* v) { \
126  tsp.reset(v); \
127  _ ## p = v; \
128  } \
129  TSP<T> p;
130 # endif
131 
132 #elif defined(_POSIX_THREADS) && (_POSIX_THREADS >= 0)
133  template< class T>
134  struct TSP {
135  pthread_key_t _key;
136  public:
137  TSP() {
138  verify( pthread_key_create( &_key, TSP::dodelete ) == 0 );
139  }
140 
141  ~TSP() {
142  pthread_key_delete( _key );
143  }
144 
145  static void dodelete( void* x ) {
146  T* t = reinterpret_cast<T*>(x);
147  delete t;
148  }
149 
150  T* get() const {
151  return reinterpret_cast<T*>( pthread_getspecific( _key ) );
152  }
153 
154  void reset(T* v) {
155  T* old = get();
156  delete old;
157  verify( pthread_setspecific( _key, v ) == 0 );
158  }
159 
160  T* getMake() {
161  T *t = get();
162  if( t == 0 ) {
163  t = new T();
164  reset( t );
165  }
166  return t;
167  }
168  };
169 
170 # define TSP_DECLARE(T,p) extern TSP<T> p;
171 
172 # define TSP_DEFINE(T,p) TSP<T> p;
173 
174 #else
175 
176  template< class T >
177  struct TSP {
178  thread_specific_ptr<T> tsp;
179  public:
180  T* get() const { return tsp.get(); }
181  void reset(T* v) { tsp.reset(v); }
182  T* getMake() {
183  T *t = get();
184  if( t == 0 )
185  reset( t = new T() );
186  return t;
187  }
188  };
189 
190 # define TSP_DECLARE(T,p) extern TSP<T> p;
191 
192 # define TSP_DEFINE(T,p) TSP<T> p;
193 
194 #endif
195 
196 }
Definition: threadlocal.h:177
remove mongo implementation macros after using
macros for mongo internals
Definition: threadlocal.h:47