threadStatic.h

Engine/source/core/threadStatic.h

More...

Classes:

Public Defines

define
ATTS(name) name
define
DITTS(type, name, initialvalue) static type name = initialvalue

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