Simbody  3.5
ThreadLocal.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_THREAD_LOCAL_H_
2 #define SimTK_SimTKCOMMON_THREAD_LOCAL_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2008-12 Stanford University and the Authors. *
13  * Authors: Peter Eastman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
27 #include <pthread.h>
28 #include <map>
29 #include <set>
30 
31 namespace SimTK {
32 
33 static std::map<void*, pthread_key_t> instanceMap;
34 static std::map<pthread_key_t, std::set<void*> > keyInstances;
35 static pthread_mutex_t keyLock = PTHREAD_MUTEX_INITIALIZER;
36 
37 template <class T>
38 static void cleanUpThreadLocalStorage(void* value) {
39 
40  // Delete the value.
41 
42  T* t = reinterpret_cast<T*>(value);
43  delete t;
44 
45  // Remove it from the set of values needing to be deleted.
46 
47  pthread_mutex_lock(&keyLock);
48  pthread_key_t key = instanceMap[value];
49  instanceMap.erase(value);
50  if (keyInstances.find(key) != keyInstances.end())
51  keyInstances.find(key)->second.erase(value);
52  pthread_mutex_unlock(&keyLock);
53 
54 }
55 
75 template <class T>
76 class ThreadLocal {
77 public:
82  this->initialize();
83  }
89  ThreadLocal(const T& defaultValue) : defaultValue(defaultValue) {
90  this->initialize();
91  }
93 
94  // Delete the key.
95 
96  pthread_key_delete(key);
97 
98  // Once the key is deleted, cleanUpThreadLocalStorage() will no longer be called, so delete
99  // all instances now.
100 
101  pthread_mutex_lock(&keyLock);
102  std::set<void*>& instances = keyInstances[key];
103  for (std::set<void*>::const_iterator iter = instances.begin(); iter != instances.end(); ++iter) {
104  instanceMap.erase(*iter);
105  delete (T*) *iter;
106  }
107  keyInstances.erase(key);
108  pthread_mutex_unlock(&keyLock);
109  }
113  T& upd() {
114  T* value = reinterpret_cast<T*>(pthread_getspecific(key));
115  if (value == NULL)
116  return createValue();
117  return *value;
118  }
122  const T& get() const {
123  T* value = reinterpret_cast<T*>(pthread_getspecific(key));
124  if (value == NULL)
125  return createValue();
126  return *value;
127  }
128 private:
129  void initialize() {
130  pthread_key_create(&key, cleanUpThreadLocalStorage<T>);
131  pthread_mutex_lock(&keyLock);
132  keyInstances[key] = std::set<void*>();
133  pthread_mutex_unlock(&keyLock);
134  }
135  T& createValue() const {
136  T* value = new T(defaultValue);
137  pthread_setspecific(key, value);
138  pthread_mutex_lock(&keyLock);
139  instanceMap[value] = key;
140  keyInstances[key].insert(value);
141  pthread_mutex_unlock(&keyLock);
142  return *value;
143  }
144  pthread_key_t key;
145  T defaultValue;
146 };
147 
148 } // namespace SimTK
149 
150 #endif // SimTK_SimTKCOMMON_THREAD_LOCAL_H_
This class represents a "thread local" variable: one which has a different value on each thread...
Definition: ThreadLocal.h:76
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
T & upd()
Get a reference to the value for the current thread.
Definition: ThreadLocal.h:113
ThreadLocal(const T &defaultValue)
Create a new ThreadLocal variable.
Definition: ThreadLocal.h:89
static std::map< void *, pthread_key_t > instanceMap
Definition: ThreadLocal.h:33
static void cleanUpThreadLocalStorage(void *value)
Definition: ThreadLocal.h:38
~ThreadLocal()
Definition: ThreadLocal.h:92
static pthread_mutex_t keyLock
Definition: ThreadLocal.h:35
static std::map< pthread_key_t, std::set< void * > > keyInstances
Definition: ThreadLocal.h:34
ThreadLocal()
Create a new ThreadLocal variable.
Definition: ThreadLocal.h:81