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
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>
[665]11#include <stdio.h>
[109]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{
[377]27        pthread_key_t mt_key;
[649]28        bool destroyed;
[1158]29
[377]30public:
[109]31
[377]32        ThreadSingleton()
33        {
34                pthread_key_create(&mt_key, &destructor);
[1158]35                destroyed = false;
[377]36        }
[109]37
[377]38        ~ThreadSingleton()
39        {
40                T* o = set(NULL);
41                if (o) delete o;
[1158]42                destroyed = true;
[377]43        }
[109]44
[377]45        static void destructor(void* o)
46        {
47                if (o)
48                        delete (T*)o;
49        }
[109]50
[377]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        }
[109]57
[377]58        T* get()
59        {
[649]60                if (destroyed) { printf("Fatal Error: accessing ThreadSingleton after destroying it\n"); return NULL; } // this will never happen
[377]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        }
[109]69
[377]70        T& getref() { return *get(); }
[109]71};
72
[346]73template<class T> class ThreadSingletonPtr
74{
[377]75        pthread_key_t mt_key;
[346]76
[377]77public:
[346]78
[377]79        ThreadSingletonPtr()
80        {
81                pthread_key_create(&mt_key, NULL);
82        }
[346]83
[377]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        }
[346]90
[377]91        T* get()
92        {
93                return (T*)pthread_getspecific(mt_key);
94        }
[346]95};
96
[348]97#else //ifdef MULTITHREADED
[109]98
[377]99#include <cstddef> //NULL
100
[371]101#define tlsGet(var) (&ThreadLocal_ ## var ## _getref())
102#define tlsGetRef(var) ThreadLocal_ ## var ## _getref()
103#define tlsSet(var,o) var.set(o)
[109]104
[371]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        }
[109]111
[348]112template<class T> class ThreadSingletonPtr
113{
[377]114        T *object;
115public:
[1158]116        ThreadSingletonPtr() :object(NULL) {}
117        T* get() { return object; }
118        T* setptr(T* o) { T* previous = object; object = o; return previous; }
[348]119};
120
121#endif //ifdef MULTITHREADED
122
[109]123////////////////////////////////////
124
[346]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)
[371]127// var is a (global) name, can't be a class member anymore because it might be implemented as function
[346]128// _PTR can only be accessed using tls...Ptr() variant of Get/Set, _ptr suffix is internally used in variable name to avoid mistakes
[109]129#ifdef USE_CPP_TLS
130
131// use c++ implementation (CPP_TLS must also be defined)
132
[371]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
[109]137
[371]138template<class T> T* _tlsGet(T*& var)
[109]139{
[377]140        if (!var)
[1158]141                var = new T();
[377]142        return var;
[109]143}
144
[371]145template<class T> T* _tlsGetPtr(T*& var)
[346]146{
[377]147        return var;
[346]148}
149
[371]150#define tlsGet(var) _tlsGet(ThreadLocal_ ## var)
151#define tlsGetRef(var) (*_tlsGet(ThreadLocal_ ## var))
[109]152
[1158]153template<class T> T* _tlsSet(T*& var, T* new_o)
[109]154{
[1158]155        T* o = var;
156        var = new_o;
[377]157        return o;
[109]158}
159
[371]160#define tlsGetPtr(var) _tlsGetPtr(ThreadLocal_ ## var)
161#define tlsSetPtr(var,o) _tlsSet(ThreadLocal_ ## var ## _ptr,o)
[346]162
[371]163#else //#ifdef USE_CPP_TLS
[109]164
165// use pthreads implementation
166
[371]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
[109]174
[371]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)
[346]179
[371]180#endif //#ifdef USE_CPP_TLS
[109]181
182
183#endif
Note: See TracBrowser for help on using the repository browser.