ThreadLocal.h
Go to the documentation of this file.00001 #ifndef SimTK_SimTKCOMMON_THREAD_LOCAL_H_
00002 #define SimTK_SimTKCOMMON_THREAD_LOCAL_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <pthread.h>
00036 #include <map>
00037 #include <set>
00038
00039 namespace SimTK {
00040
00041 static std::map<void*, pthread_key_t> instanceMap;
00042 static std::map<pthread_key_t, std::set<void*> > keyInstances;
00043 static pthread_mutex_t keyLock = PTHREAD_MUTEX_INITIALIZER;
00044
00045 template <class T>
00046 static void cleanUpThreadLocalStorage(void* value) {
00047
00048
00049
00050 T* t = reinterpret_cast<T*>(value);
00051 delete t;
00052
00053
00054
00055 pthread_mutex_lock(&keyLock);
00056 pthread_key_t key = instanceMap[value];
00057 instanceMap.erase(value);
00058 if (keyInstances.find(key) != keyInstances.end())
00059 keyInstances.find(key)->second.erase(value);
00060 pthread_mutex_unlock(&keyLock);
00061
00062 }
00063
00083 template <class T>
00084 class ThreadLocal {
00085 public:
00089 ThreadLocal() {
00090 this->initialize();
00091 }
00097 ThreadLocal(const T& defaultValue) : defaultValue(defaultValue) {
00098 this->initialize();
00099 }
00100 ~ThreadLocal() {
00101
00102
00103
00104 pthread_key_delete(key);
00105
00106
00107
00108
00109 pthread_mutex_lock(&keyLock);
00110 std::set<void*>& instances = keyInstances[key];
00111 for (std::set<void*>::const_iterator iter = instances.begin(); iter != instances.end(); ++iter) {
00112 instanceMap.erase(*iter);
00113 delete (T*) *iter;
00114 }
00115 keyInstances.erase(key);
00116 pthread_mutex_unlock(&keyLock);
00117 }
00121 T& upd() {
00122 T* value = reinterpret_cast<T*>(pthread_getspecific(key));
00123 if (value == NULL)
00124 return createValue();
00125 return *value;
00126 }
00130 const T& get() const {
00131 T* value = reinterpret_cast<T*>(pthread_getspecific(key));
00132 if (value == NULL)
00133 return createValue();
00134 return *value;
00135 }
00136 private:
00137 void initialize() {
00138 pthread_key_create(&key, cleanUpThreadLocalStorage<T>);
00139 pthread_mutex_lock(&keyLock);
00140 keyInstances[key] = std::set<void*>();
00141 pthread_mutex_unlock(&keyLock);
00142 }
00143 T& createValue() const {
00144 T* value = new T(defaultValue);
00145 pthread_setspecific(key, value);
00146 pthread_mutex_lock(&keyLock);
00147 instanceMap[value] = key;
00148 keyInstances[key].insert(value);
00149 pthread_mutex_unlock(&keyLock);
00150 return *value;
00151 }
00152 pthread_key_t key;
00153 T defaultValue;
00154 };
00155
00156 }
00157
00158 #endif // SimTK_SimTKCOMMON_THREAD_LOCAL_H_