source: cpp/common/threads.h @ 438

Last change on this file since 438 was 377, checked in by Maciej Komosinski, 10 years ago

Included header for NULL

  • Property svn:eol-style set to native
File size: 4.0 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;
[109]27
[377]28public:
[109]29
[377]30        ThreadSingleton()
31        {
32                pthread_key_create(&mt_key, &destructor);
33        }
[109]34
[377]35        ~ThreadSingleton()
36        {
37                T* o = set(NULL);
38                if (o) delete o;
39        }
[109]40
[377]41        static void destructor(void* o)
42        {
43                if (o)
44                        delete (T*)o;
45        }
[109]46
[377]47        T* set(T* new_o)
48        {
49                T* o = (T*)pthread_getspecific(mt_key);
50                pthread_setspecific(mt_key, new_o);
51                return o;
52        }
[109]53
[377]54        T* get()
55        {
56                T* o = (T*)pthread_getspecific(mt_key);
57                if (!o)
58                {
59                        o = new T();
60                        pthread_setspecific(mt_key, o);
61                }
62                return o;
63        }
[109]64
[377]65        T& getref() { return *get(); }
[109]66};
67
[346]68template<class T> class ThreadSingletonPtr
69{
[377]70        pthread_key_t mt_key;
[346]71
[377]72public:
[346]73
[377]74        ThreadSingletonPtr()
75        {
76                pthread_key_create(&mt_key, NULL);
77        }
[346]78
[377]79        T* setptr(T* new_o)
80        {
81                T* o = (T*)pthread_getspecific(mt_key);
82                pthread_setspecific(mt_key, new_o);
83                return o;
84        }
[346]85
[377]86        T* get()
87        {
88                return (T*)pthread_getspecific(mt_key);
89        }
[346]90};
91
[348]92#else //ifdef MULTITHREADED
[109]93
[377]94#include <cstddef> //NULL
95
[371]96#define tlsGet(var) (&ThreadLocal_ ## var ## _getref())
97#define tlsGetRef(var) ThreadLocal_ ## var ## _getref()
98#define tlsSet(var,o) var.set(o)
[109]99
[371]100#define THREAD_LOCAL_DECL(cls,var) cls& ThreadLocal_ ## var ## _getref()
101#define THREAD_LOCAL_DEF(cls,var) cls& ThreadLocal_ ## var ## _getref() \
102        { \
103        static cls object; \
104        return object; \
105        }
[109]106
[348]107template<class T> class ThreadSingletonPtr
108{
[377]109        T *object;
110public:
111        ThreadSingletonPtr():object(NULL) {}
112        T* get() {return object;}
113        T* setptr(T* o) {T* previous=object; object=o; return previous;}
[348]114};
115
116#endif //ifdef MULTITHREADED
117
[109]118////////////////////////////////////
119
[346]120// THREAD_LOCAL(cls) - behaves like object of class cls (automatic creation/destruction)
121// THREAD_LOCAL(cls)..._PTR - behaves like pointer to cls (initial NULL, no autocreation/destruction)
[371]122// var is a (global) name, can't be a class member anymore because it might be implemented as function
[346]123// _PTR can only be accessed using tls...Ptr() variant of Get/Set, _ptr suffix is internally used in variable name to avoid mistakes
[109]124#ifdef USE_CPP_TLS
125
126// use c++ implementation (CPP_TLS must also be defined)
127
[371]128#define THREAD_LOCAL_DECL(cls,var) CPP_TLS cls* ThreadLocal_ ## var
129#define THREAD_LOCAL_DEF(cls,var) CPP_TLS cls* ThreadLocal_ ## var=NULL
130#define THREAD_LOCAL_DECL_PTR(cls,var) CPP_TLS cls* ThreadLocal_ ## var ## _ptr
131#define THREAD_LOCAL_DEF_PTR(cls,var) CPP_TLS cls* ThreadLocal_ ## var ## _ptr=NULL
[109]132
[371]133template<class T> T* _tlsGet(T*& var)
[109]134{
[377]135        if (!var)
136                var=new T();
137        return var;
[109]138}
139
[371]140template<class T> T* _tlsGetPtr(T*& var)
[346]141{
[377]142        return var;
[346]143}
144
[371]145#define tlsGet(var) _tlsGet(ThreadLocal_ ## var)
146#define tlsGetRef(var) (*_tlsGet(ThreadLocal_ ## var))
[109]147
[371]148template<class T> T* _tlsSet(T*& var,T* new_o)
[109]149{
[377]150        T* o=var;
151        var=new_o;
152        return o;
[109]153}
154
[371]155#define tlsGetPtr(var) _tlsGetPtr(ThreadLocal_ ## var)
156#define tlsSetPtr(var,o) _tlsSet(ThreadLocal_ ## var ## _ptr,o)
[346]157
[371]158#else //#ifdef USE_CPP_TLS
[109]159
160// use pthreads implementation
161
[371]162#ifdef MULTITHREADED
163#define THREAD_LOCAL_DECL(cls,var) ThreadSingleton<cls> ThreadLocal_ ## var
164#define THREAD_LOCAL_DEF(cls,var) ThreadSingleton<cls> ThreadLocal_ ## var
165#define tlsGet(var) ThreadLocal_ ## var.get()
166#define tlsGetRef(var) ThreadLocal_ ## var.getref()
167#define tlsSet(var,o) ThreadLocal_ ## var.set(o)
168#endif
[109]169
[371]170#define THREAD_LOCAL_DECL_PTR(cls,var) extern ThreadSingletonPtr<cls> ThreadLocal_ ## var ## _ptr
171#define THREAD_LOCAL_DEF_PTR(cls,var) ThreadSingletonPtr<cls> ThreadLocal_ ## var ## _ptr
172#define tlsGetPtr(var) ThreadLocal_ ## var ## _ptr.get()
173#define tlsSetPtr(var,o) ThreadLocal_ ## var ## _ptr.setptr(o)
[346]174
[371]175#endif //#ifdef USE_CPP_TLS
[109]176
177
178#endif
Note: See TracBrowser for help on using the repository browser.