Simbody

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  *                      SimTK Core: SimTK Simbody(tm)                         *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2008 Stanford University and the Authors.           *
00013  * Authors: Peter Eastman                                                     *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
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     // Delete the value.
00049     
00050     T* t = reinterpret_cast<T*>(value);
00051     delete t;
00052     
00053     // Remove it from the set of values needing to be deleted.
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         // Delete the key.
00103         
00104         pthread_key_delete(key);
00105         
00106         // Once the key is deleted, cleanUpThreadLocalStorage() will no longer be called, so delete
00107         // all instances now.
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 } // namespace SimTK
00157 
00158 #endif // SimTK_SimTKCOMMON_THREAD_LOCAL_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines