threadStatic.h 8.6 KB

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