threadStatic.h
Engine/source/core/threadStatic.h
Classes:
Public Defines
Public Typedefs
TorqueThreadStaticList
TorqueThreadStaticListHandle
Detailed Description
Public Defines
ATTS(name) name
DITTS(type, name, initialvalue) static type name = initialvalue
Public Typedefs
typedef VectorPtr< _TorqueThreadStatic * > TorqueThreadStaticList
typedef TorqueThreadStaticList * TorqueThreadStaticListHandle
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#ifndef _TORQUETHREADSTATIC_H_ 25#define _TORQUETHREADSTATIC_H_ 26 27#include "core/util/tVector.h" 28 29//----------------------------------------------------------------------------- 30// TorqueThreadStatic Base Class 31class _TorqueThreadStatic 32{ 33 friend class _TorqueThreadStaticReg; 34 35private: 36 37#ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS 38 U32 mHitCount; 39#endif 40 41protected: 42 static U32 mListIndex; 43 virtual _TorqueThreadStatic *_createInstance() const = 0; 44 45public: 46 _TorqueThreadStatic() 47#ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS 48 : mHitCount( 0 ) 49#endif 50 { }; 51 virtual ~_TorqueThreadStatic() { } 52 53 static const U32 getListIndex(){ return mListIndex; } 54 55 virtual void *getMemInstPtr() = 0; 56 virtual const void *getConstMemInstPtr() const = 0; 57 virtual const dsize_t getMemInstSize() const = 0; 58 59#ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS 60 _TorqueThreadStatic *_chainHit() { mHitCount++; return this; } 61 const U32 &trackHit() { return ++mHitCount; } 62 const U32 &getHitCount() const { return mHitCount; } 63#endif 64}; 65// Typedef 66typedef VectorPtr<_TorqueThreadStatic*> TorqueThreadStaticList; 67typedef TorqueThreadStaticList * TorqueThreadStaticListHandle; 68 69//----------------------------------------------------------------------------- 70// Auto-registration class and manager of the instances 71class _TorqueThreadStaticReg 72{ 73 // This will manage all of the thread static registrations 74 static _TorqueThreadStaticReg *smFirst; 75 _TorqueThreadStaticReg *mNext; 76 77 // This is a vector of vectors which will store instances of thread static 78 // variables. mThreadStaticInsances[0] will be the list of the initial values 79 // of the statics, and then indexing for instanced versions will start at 1 80 // 81 // Note that the list of instances in mThreadStaticInstances[0] does not, and 82 // must not get 'delete' called on it, because all members of the list are 83 // pointers to statically allocated memory. All other lists will be contain 84 // pointers to dynamically allocated memory, and will need to be freed upon 85 // termination. 86 // 87 // So this was originally a static data member, however that caused problems because 88 // I was relying on static initialization order to make sure the vector got initialized 89 // *before* any static instance of this class was created via macro. By wrapping the 90 // static in a function, I can be assured that the static memory will get initialized 91 // before it is modified. 92 static Vector<TorqueThreadStaticList> &getThreadStaticListVector(); 93 94public: 95 /// Constructor 96 _TorqueThreadStaticReg( _TorqueThreadStatic *ttsInitial ) 97 { 98 // Link this entry into the list 99 mNext = smFirst; 100 smFirst = this; 101 102 // Create list 0 (initial values) if it doesn't exist 103 if( getThreadStaticListVector().empty() ) 104 getThreadStaticListVector().increment(); 105 106 // Set the index of the thread static for lookup 107 ttsInitial->mListIndex = getThreadStaticListVector()[0].size(); 108 109 // Add the static to the initial value list 110 getThreadStaticListVector()[0].push_back( ttsInitial ); 111 } 112 113 virtual ~_TorqueThreadStaticReg(); 114 115 // Accessors 116 static const TorqueThreadStaticList &getStaticList( const U32 idx = 0 ) 117 { 118 AssertFatal( getThreadStaticListVector().size() > idx, "Out of range static list" ); 119 120 return getThreadStaticListVector()[idx]; 121 } 122 123 static void destroyInstances(); 124 static void destroyInstance( TorqueThreadStaticList *instanceList ); 125 126 static const _TorqueThreadStaticReg *getFirst() { return smFirst; } 127 128 const _TorqueThreadStaticReg *getNext() const { return mNext; } 129 130 /// Spawn another copy of the ThreadStatics and pass back the id 131 static TorqueThreadStaticListHandle spawnThreadStaticsInstance(); 132}; 133 134//----------------------------------------------------------------------------- 135// Template class that will get used as a base for the thread statics 136template<class T> 137class TorqueThreadStatic : public _TorqueThreadStatic 138{ 139 // The reg object will want access to mInstance 140 friend class _TorqueThreadStaticReg; 141 142private: 143 T mInstance; 144 145public: 146 TorqueThreadStatic( T instanceVal ) : mInstance( instanceVal ) {} 147 virtual void *getMemInstPtr() { return &mInstance; } 148 virtual const void *getConstMemInstPtr() const { return &mInstance; } 149 150 // I am not sure these are needed, and I don't want to create confusing-to-debug code 151#if 0 152 // Operator overloads 153 operator T*() { return &mInstance; } 154 operator T*() const { return &mInstance; } 155 operator const T*() const { return &mInstance; } 156 157 bool operator ==( const T &l ) const { return mInstance == l; } 158 bool operator !=( const T &l ) const { return mInstance != l; } 159 160 T &l ) { mInstance = l; return mInstance; } 161#endif // if0 162}; 163 164//----------------------------------------------------------------------------- 165// If ThreadStatic behavior is not enabled, than the macros will resolve 166// to regular, static memory 167#ifndef TORQUE_ENABLE_THREAD_STATICS 168 169#define DITTS( type, name, initialvalue ) static type name = initialvalue 170#define ATTS( name ) name 171 172#else // TORQUE_ENABLE_THREAD_STATICS is defined 173 174//----------------------------------------------------------------------------- 175// Declare TorqueThreadStatic, and initialize it's value 176// 177// This macro would be used in a .cpp file to declare a ThreadStatic 178#define DITTS(type, name, initalvalue) \ 179class _##name##TorqueThreadStatic : public TorqueThreadStatic<type> \ 180{ \ 181protected:\ 182 virtual _TorqueThreadStatic *_createInstance() const { return new _##name##TorqueThreadStatic; } \ 183public: \ 184 _##name##TorqueThreadStatic() : TorqueThreadStatic<type>( initalvalue ) {} \ 185 virtual const dsize_t getMemInstSize() const { return sizeof( type ); } \ 186 type &_cast() { return *reinterpret_cast<type *>( getMemInstPtr() ); } \ 187 const type &_const_cast() const { return *reinterpret_cast<const type *>( getConstMemInstPtr() ); } \ 188}; \ 189static _##name##TorqueThreadStatic name##TorqueThreadStatic; \ 190static _TorqueThreadStaticReg _##name##TTSReg( reinterpret_cast<_TorqueThreadStatic *>( & name##TorqueThreadStatic ) ) 191 192//----------------------------------------------------------------------------- 193// Access TorqueThreadStatic 194 195// NOTE: TEMPDEF is there as a temporary place holder for however we want to get the index of the currently running 196// thread or whatever. 197#define TEMPDEF 0 198 199#ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS 200// Access counting macro 201# define ATTS_(name, idx) \ 202 (reinterpret_cast< _##name##TorqueThreadStatic *>( _TorqueThreadStaticReg::getStaticList( idx )[ _##name##TorqueThreadStatic::getListIndex() ]->_chainHit() )->_cast() ) 203// Const access counting macro 204# define CATTS_(name, idx) \ 205 (reinterpret_cast< _##name##TorqueThreadStatic *>( _TorqueThreadStaticReg::getStaticList( idx )[ _##name##TorqueThreadStatic::getListIndex() ]->_chainHit() )->_const_cast() ) 206#else 207// Regular access macro 208# define ATTS_(name, idx) \ 209 (reinterpret_cast< _##name##TorqueThreadStatic *>( _TorqueThreadStaticReg::getStaticList( idx )[ _##name##TorqueThreadStatic::getListIndex() ] )->_cast() ) 210// Const access macro 211# define CATTS_(name, idx) \ 212 (reinterpret_cast< _##name##TorqueThreadStatic *>( _TorqueThreadStaticReg::getStaticList( idx )[ _##name##TorqueThreadStatic::getListIndex() ] )->_const_cast() ) 213#endif // TORQUE_ENABLE_THREAD_STATIC_METRICS 214 215#define ATTS(name) ATTS_(name, TEMPDEF) 216#define CATTS(name) CATTS_(name, TEMPDEF) 217 218#endif // TORQUE_ENABLE_THREAD_STATICS 219 220#endif 221