source: cpp/common/threads.h @ 1304

Last change on this file since 1304 was 1158, checked in by Maciej Komosinski, 3 years ago

Cosmetic/minor improvements

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