source: cpp/common/threads.h @ 371

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

THREAD_LOCAL uses ThreadLocal_ prefix for variables. The static object inside the single-threaded implementation is no longer associated with a class.

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