CLucene - a full-featured, c++ search engine
API Documentation
00001 /*------------------------------------------------------------------------------ 00002 * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team 00003 * 00004 * Distributable under the terms of either the Apache License (Version 2.0) or 00005 * the GNU Lesser General Public License, as specified in the COPYING file. 00006 ------------------------------------------------------------------------------*/ 00007 #ifndef _lucene_util_ThreadLocal_H 00008 #define _lucene_util_ThreadLocal_H 00009 00010 #if defined(_LUCENE_PRAGMA_ONCE) 00011 # pragma once 00012 #endif 00013 00014 #include "CLucene/util/VoidMap.h" 00015 00016 CL_NS_DEF(util) 00017 00018 class ThreadLocalBase: LUCENE_BASE{ 00019 public: 00025 typedef void ShutdownHook(bool startup); 00026 00027 protected: 00028 STATIC_DEFINE_MUTEX(ThreadLocalBase_THIS_LOCK) 00029 typedef CL_NS(util)::CLMultiMap<_LUCENE_THREADID_TYPE, ThreadLocalBase*, 00030 CL_NS(util)::CLuceneThreadIdCompare, 00031 CL_NS(util)::Deletor::ConstNullVal<_LUCENE_THREADID_TYPE>, 00032 CL_NS(util)::Deletor::ConstNullVal<ThreadLocalBase*> > ThreadLocalsType; 00033 static ThreadLocalsType threadLocals; 00034 //todo: using http://en.wikipedia.org/wiki/Thread-local_storage#Pthreads_implementation 00035 //would work better... but lots of testing would be needed first... 00036 typedef CL_NS(util)::CLSetList<ShutdownHook*, 00037 CL_NS(util)::Compare::Void<ShutdownHook>, 00038 CL_NS(util)::Deletor::ConstNullVal<ShutdownHook*> > ShutdownHooksType; 00039 static ShutdownHooksType shutdownHooks; 00040 00041 ThreadLocalBase(); 00042 public: 00043 virtual ~ThreadLocalBase(); 00044 00051 virtual void setNull() = 0; 00052 00060 static void UnregisterCurrentThread(); 00061 00065 static void shutdown(); 00066 00071 static void registerShutdownHook(ShutdownHook* hook); 00072 }; 00073 00074 template<typename T,typename _deletor> 00075 class ThreadLocal: public ThreadLocalBase{ 00076 typedef CL_NS(util)::CLSet<_LUCENE_THREADID_TYPE, T, 00077 CL_NS(util)::CLuceneThreadIdCompare, 00078 CL_NS(util)::Deletor::ConstNullVal<_LUCENE_THREADID_TYPE>, 00079 _deletor > LocalsType; 00080 LocalsType locals; 00081 DEFINE_MUTEX(locals_LOCK) 00082 public: 00083 ThreadLocal(); 00084 ~ThreadLocal(); 00085 T get(); 00086 void setNull(); 00087 void set(T t); 00088 }; 00089 00090 template<typename T,typename _deletor> 00091 ThreadLocal<T,_deletor>::ThreadLocal(): 00092 locals(false,true) 00093 { 00094 //add this object to the base's list of threadlocals to be 00095 //notified in case of UnregisterThread() 00096 _LUCENE_THREADID_TYPE id = _LUCENE_CURRTHREADID; 00097 SCOPED_LOCK_MUTEX(ThreadLocalBase_THIS_LOCK) 00098 threadLocals.insert( pair<const _LUCENE_THREADID_TYPE, ThreadLocalBase*>(id, this) ); 00099 } 00100 00101 template<typename T,typename _deletor> 00102 ThreadLocal<T,_deletor>::~ThreadLocal(){ 00103 //remove this object to the base's list of threadlocals 00104 _LUCENE_THREADID_TYPE id = _LUCENE_CURRTHREADID; 00105 SCOPED_LOCK_MUTEX(ThreadLocalBase_THIS_LOCK) 00106 00107 //remove all the thread local data for this object 00108 locals.clear(); 00109 00110 //remove this object from the ThreadLocalBase threadLocal list 00111 ThreadLocalsType::iterator itr = threadLocals.lower_bound(id); 00112 ThreadLocalsType::iterator end = threadLocals.upper_bound(id); 00113 while ( itr != end ){ 00114 if ( itr->second == this){ 00115 threadLocals.erase(itr); 00116 break; 00117 } 00118 ++itr; 00119 } 00120 } 00121 00122 template<typename T,typename _deletor> 00123 T ThreadLocal<T,_deletor>::get(){ 00124 return locals.get(_LUCENE_CURRTHREADID); 00125 } 00126 00127 template<typename T,typename _deletor> 00128 void ThreadLocal<T,_deletor>::setNull(){ 00129 set(NULL); 00130 } 00131 00132 template<typename T,typename _deletor> 00133 void ThreadLocal<T,_deletor>::set(T t){ 00134 _LUCENE_THREADID_TYPE id = _LUCENE_CURRTHREADID; 00135 locals.remove(id); 00136 if ( t != NULL ) 00137 locals.insert( pair<_LUCENE_THREADID_TYPE,T>(id, t) ); 00138 } 00139 00140 CL_NS_END 00141 #endif