source: cpp/common/threads.h @ 649

Last change on this file since 649 was 649, checked in by Maciej Komosinski, 7 years ago

Display diagnostic message when threads not released properly

  • Property svn:eol-style set to native
File size: 4.2 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
[122]4
[109]5#ifndef _THREADS_H_
6#define _THREADS_H_
7
8#ifdef MULTITHREADED
9
10#include <pthread.h>
11
12int sysGetCPUCount();
13
14#ifdef LINUX
15//#define USE_CPP_TLS
16//#define CPP_TLS __thread
17#endif
18
19#ifdef __BORLANDC__ //zakladamy ze wszyscy uzywaja pthreadsowych, bo w tych wbudowanych w c++ w obecnym standardzie nie ma destrukcji obiektow (tylko proste struktury)
20//#define USE_CPP_TLS
21//#define CPP_TLS __declspec(thread)
22#endif
23
24template<class T> class ThreadSingleton
25{
[377]26        pthread_key_t mt_key;
[649]27        bool destroyed;
28       
[377]29public:
[109]30
[377]31        ThreadSingleton()
32        {
33                pthread_key_create(&mt_key, &destructor);
[649]34                destroyed=false;
[377]35        }
[109]36
[377]37        ~ThreadSingleton()
38        {
39                T* o = set(NULL);
40                if (o) delete o;
[649]41                destroyed=true;
[377]42        }
[109]43
[377]44        static void destructor(void* o)
45        {
46                if (o)
47                        delete (T*)o;
48        }
[109]49
[377]50        T* set(T* new_o)
51        {
52                T* o = (T*)pthread_getspecific(mt_key);
53                pthread_setspecific(mt_key, new_o);
54                return o;
55        }
[109]56
[377]57        T* get()
58        {
[649]59                if (destroyed) { printf("Fatal Error: accessing ThreadSingleton after destroying it\n"); return NULL; } // this will never happen
[377]60                T* o = (T*)pthread_getspecific(mt_key);
61                if (!o)
62                {
63                        o = new T();
64                        pthread_setspecific(mt_key, o);
65                }
66                return o;
67        }
[109]68
[377]69        T& getref() { return *get(); }
[109]70};
71
[346]72template<class T> class ThreadSingletonPtr
73{
[377]74        pthread_key_t mt_key;
[346]75
[377]76public:
[346]77
[377]78        ThreadSingletonPtr()
79        {
80                pthread_key_create(&mt_key, NULL);
81        }
[346]82
[377]83        T* setptr(T* new_o)
84        {
85                T* o = (T*)pthread_getspecific(mt_key);
86                pthread_setspecific(mt_key, new_o);
87                return o;
88        }
[346]89
[377]90        T* get()
91        {
92                return (T*)pthread_getspecific(mt_key);
93        }
[346]94};
95
[348]96#else //ifdef MULTITHREADED
[109]97
[377]98#include <cstddef> //NULL
99
[371]100#define tlsGet(var) (&ThreadLocal_ ## var ## _getref())
101#define tlsGetRef(var) ThreadLocal_ ## var ## _getref()
102#define tlsSet(var,o) var.set(o)
[109]103
[371]104#define THREAD_LOCAL_DECL(cls,var) cls& ThreadLocal_ ## var ## _getref()
105#define THREAD_LOCAL_DEF(cls,var) cls& ThreadLocal_ ## var ## _getref() \
106        { \
107        static cls object; \
108        return object; \
109        }
[109]110
[348]111template<class T> class ThreadSingletonPtr
112{
[377]113        T *object;
114public:
115        ThreadSingletonPtr():object(NULL) {}
116        T* get() {return object;}
117        T* setptr(T* o) {T* previous=object; object=o; return previous;}
[348]118};
119
120#endif //ifdef MULTITHREADED
121
[109]122////////////////////////////////////
123
[346]124// THREAD_LOCAL(cls) - behaves like object of class cls (automatic creation/destruction)
125// THREAD_LOCAL(cls)..._PTR - behaves like pointer to cls (initial NULL, no autocreation/destruction)
[371]126// var is a (global) name, can't be a class member anymore because it might be implemented as function
[346]127// _PTR can only be accessed using tls...Ptr() variant of Get/Set, _ptr suffix is internally used in variable name to avoid mistakes
[109]128#ifdef USE_CPP_TLS
129
130// use c++ implementation (CPP_TLS must also be defined)
131
[371]132#define THREAD_LOCAL_DECL(cls,var) CPP_TLS cls* ThreadLocal_ ## var
133#define THREAD_LOCAL_DEF(cls,var) CPP_TLS cls* ThreadLocal_ ## var=NULL
134#define THREAD_LOCAL_DECL_PTR(cls,var) CPP_TLS cls* ThreadLocal_ ## var ## _ptr
135#define THREAD_LOCAL_DEF_PTR(cls,var) CPP_TLS cls* ThreadLocal_ ## var ## _ptr=NULL
[109]136
[371]137template<class T> T* _tlsGet(T*& var)
[109]138{
[377]139        if (!var)
140                var=new T();
141        return var;
[109]142}
143
[371]144template<class T> T* _tlsGetPtr(T*& var)
[346]145{
[377]146        return var;
[346]147}
148
[371]149#define tlsGet(var) _tlsGet(ThreadLocal_ ## var)
150#define tlsGetRef(var) (*_tlsGet(ThreadLocal_ ## var))
[109]151
[371]152template<class T> T* _tlsSet(T*& var,T* new_o)
[109]153{
[377]154        T* o=var;
155        var=new_o;
156        return o;
[109]157}
158
[371]159#define tlsGetPtr(var) _tlsGetPtr(ThreadLocal_ ## var)
160#define tlsSetPtr(var,o) _tlsSet(ThreadLocal_ ## var ## _ptr,o)
[346]161
[371]162#else //#ifdef USE_CPP_TLS
[109]163
164// use pthreads implementation
165
[371]166#ifdef MULTITHREADED
167#define THREAD_LOCAL_DECL(cls,var) ThreadSingleton<cls> ThreadLocal_ ## var
168#define THREAD_LOCAL_DEF(cls,var) ThreadSingleton<cls> ThreadLocal_ ## var
169#define tlsGet(var) ThreadLocal_ ## var.get()
170#define tlsGetRef(var) ThreadLocal_ ## var.getref()
171#define tlsSet(var,o) ThreadLocal_ ## var.set(o)
172#endif
[109]173
[371]174#define THREAD_LOCAL_DECL_PTR(cls,var) extern ThreadSingletonPtr<cls> ThreadLocal_ ## var ## _ptr
175#define THREAD_LOCAL_DEF_PTR(cls,var) ThreadSingletonPtr<cls> ThreadLocal_ ## var ## _ptr
176#define tlsGetPtr(var) ThreadLocal_ ## var ## _ptr.get()
177#define tlsSetPtr(var,o) ThreadLocal_ ## var ## _ptr.setptr(o)
[346]178
[371]179#endif //#ifdef USE_CPP_TLS
[109]180
181
182#endif
Note: See TracBrowser for help on using the repository browser.