// This file is a part of Framsticks SDK. http://www.framsticks.com/ // Copyright (C) 1999-2015 Maciej Komosinski and Szymon Ulatowski. // See LICENSE.txt for details. #ifndef _THREADS_H_ #define _THREADS_H_ #ifdef MULTITHREADED #include int sysGetCPUCount(); #ifdef LINUX //#define USE_CPP_TLS //#define CPP_TLS __thread #endif #ifdef __BORLANDC__ //zakladamy ze wszyscy uzywaja pthreadsowych, bo w tych wbudowanych w c++ w obecnym standardzie nie ma destrukcji obiektow (tylko proste struktury) //#define USE_CPP_TLS //#define CPP_TLS __declspec(thread) #endif template class ThreadSingleton { pthread_key_t mt_key; public: ThreadSingleton() { pthread_key_create(&mt_key,&destructor); } ~ThreadSingleton() { T* o=set(NULL); if (o) delete o; } static void destructor(void* o) { if (o) delete (T*)o; } T* set(T* new_o) { T* o=(T*)pthread_getspecific(mt_key); pthread_setspecific(mt_key,new_o); return o; } T* get() { T* o=(T*)pthread_getspecific(mt_key); if (!o) { o=new T(); pthread_setspecific(mt_key,o); } return o; } T& getref() {return *get();} }; template class ThreadSingletonPtr { pthread_key_t mt_key; public: ThreadSingletonPtr() { pthread_key_create(&mt_key,NULL); } T* setptr(T* new_o) { T* o=(T*)pthread_getspecific(mt_key); pthread_setspecific(mt_key,new_o); return o; } T* get() { return (T*)pthread_getspecific(mt_key); } }; #else template class ThreadSingleton { T object; public: T* get() {return &object;} T& getref() {return object;} }; #endif //////////////////////////////////// // THREAD_LOCAL(cls) - behaves like object of class cls (automatic creation/destruction) // THREAD_LOCAL(cls)..._PTR - behaves like pointer to cls (initial NULL, no autocreation/destruction) // _PTR can only be accessed using tls...Ptr() variant of Get/Set, _ptr suffix is internally used in variable name to avoid mistakes #ifdef USE_CPP_TLS // use c++ implementation (CPP_TLS must also be defined) #define THREAD_LOCAL_DECL(cls,var) CPP_TLS cls* var #define THREAD_LOCAL_DEF(cls,var) CPP_TLS cls* var=NULL #define THREAD_LOCAL_DECL_PTR(cls,var) CPP_TLS cls* var ## _ptr #define THREAD_LOCAL_DEF_PTR(cls,var) CPP_TLS cls* var ## _ptr=NULL template T* tlsGet(T*& var) { if (!var) var=new T(); return var; } template T* tlsGetPtr(T*& var) { return var; } #define tlsGetRef(var) (*tlsGet(var)) template T* tlsSet(T*& var,T* new_o) { T* o=var; var=new_o; return o; } #define tlsGetSetPtr(var,o) tlsSet(var ## _ptr,o) #else // use pthreads implementation #define THREAD_LOCAL_DECL(cls,var) ThreadSingleton var #define THREAD_LOCAL_DEF(cls,var) ThreadSingleton var #define tlsGet(var) var.get() #define tlsGetRef(var) var.getref() #define tlsSet(var,o) var.set(o) #define THREAD_LOCAL_DECL_PTR(cls,var) ThreadSingletonPtr var ## _ptr #define THREAD_LOCAL_DEF_PTR(cls,var) ThreadSingletonPtr var ## _ptr #define tlsGetPtr(var) var ## _ptr.get() #define tlsSetPtr(var,o) var ## _ptr.setptr(o) #endif #endif