as_thread.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2011 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_thread.cpp
  25. //
  26. // Functions for multi threading support
  27. //
  28. #include "as_config.h"
  29. #include "as_thread.h"
  30. #include "as_atomic.h"
  31. BEGIN_AS_NAMESPACE
  32. // Singleton
  33. asCThreadManager *threadManager = 0;
  34. //======================================================================
  35. extern "C"
  36. {
  37. AS_API int asThreadCleanup()
  38. {
  39. // As this function can be called globally,
  40. // we can't assume the threadManager exists
  41. if( threadManager )
  42. return threadManager->CleanupLocalData();
  43. return 0;
  44. }
  45. }
  46. //======================================================================
  47. asCThreadManager::asCThreadManager()
  48. {
  49. #ifdef AS_NO_THREADS
  50. tld = 0;
  51. #endif
  52. refCount.set(1);
  53. }
  54. void asCThreadManager::AddRef()
  55. {
  56. refCount.atomicInc();
  57. }
  58. void asCThreadManager::Release()
  59. {
  60. if( refCount.atomicDec() == 0 )
  61. {
  62. // The last engine has been destroyed, so we
  63. // need to delete the thread manager as well
  64. asDELETE(this,asCThreadManager);
  65. threadManager = 0;
  66. }
  67. }
  68. asCThreadManager::~asCThreadManager()
  69. {
  70. #ifndef AS_NO_THREADS
  71. ENTERCRITICALSECTION(criticalSection);
  72. // Delete all thread local datas
  73. asSMapNode<asPWORD,asCThreadLocalData*> *cursor = 0;
  74. if( tldMap.MoveFirst(&cursor) )
  75. {
  76. do
  77. {
  78. if( tldMap.GetValue(cursor) )
  79. {
  80. asDELETE(tldMap.GetValue(cursor),asCThreadLocalData);
  81. }
  82. } while( tldMap.MoveNext(&cursor, cursor) );
  83. }
  84. LEAVECRITICALSECTION(criticalSection);
  85. #else
  86. if( tld )
  87. {
  88. asDELETE(tld,asCThreadLocalData);
  89. }
  90. tld = 0;
  91. #endif
  92. }
  93. int asCThreadManager::CleanupLocalData()
  94. {
  95. #ifndef AS_NO_THREADS
  96. int r = 0;
  97. #if defined AS_POSIX_THREADS
  98. asPWORD id = (asPWORD)pthread_self();
  99. #elif defined AS_WINDOWS_THREADS
  100. asPWORD id = (asPWORD)GetCurrentThreadId();
  101. #endif
  102. ENTERCRITICALSECTION(criticalSection);
  103. asSMapNode<asPWORD,asCThreadLocalData*> *cursor = 0;
  104. if( tldMap.MoveTo(&cursor, id) )
  105. {
  106. asCThreadLocalData *tld = tldMap.GetValue(cursor);
  107. // Can we really remove it at this time?
  108. if( tld->activeContexts.GetLength() == 0 )
  109. {
  110. asDELETE(tld,asCThreadLocalData);
  111. tldMap.Erase(cursor);
  112. r = 0;
  113. }
  114. else
  115. r = asCONTEXT_ACTIVE;
  116. }
  117. LEAVECRITICALSECTION(criticalSection);
  118. return r;
  119. #else
  120. if( tld )
  121. {
  122. if( tld->activeContexts.GetLength() == 0 )
  123. {
  124. asDELETE(tld,asCThreadLocalData);
  125. tld = 0;
  126. }
  127. else
  128. return asCONTEXT_ACTIVE;
  129. }
  130. return 0;
  131. #endif
  132. }
  133. #ifndef AS_NO_THREADS
  134. asCThreadLocalData *asCThreadManager::GetLocalData(asPWORD threadId)
  135. {
  136. asCThreadLocalData *tld = 0;
  137. ENTERCRITICALSECTION(criticalSection);
  138. asSMapNode<asPWORD,asCThreadLocalData*> *cursor = 0;
  139. if( tldMap.MoveTo(&cursor, threadId) )
  140. tld = tldMap.GetValue(cursor);
  141. LEAVECRITICALSECTION(criticalSection);
  142. return tld;
  143. }
  144. void asCThreadManager::SetLocalData(asPWORD threadId, asCThreadLocalData *tld)
  145. {
  146. ENTERCRITICALSECTION(criticalSection);
  147. tldMap.Insert(threadId, tld);
  148. LEAVECRITICALSECTION(criticalSection);
  149. }
  150. #endif
  151. asCThreadLocalData *asCThreadManager::GetLocalData()
  152. {
  153. #ifndef AS_NO_THREADS
  154. #if defined AS_POSIX_THREADS
  155. asPWORD id = (asPWORD)pthread_self();
  156. #elif defined AS_WINDOWS_THREADS
  157. asPWORD id = (asPWORD)GetCurrentThreadId();
  158. #endif
  159. asCThreadLocalData *tld = GetLocalData(id);
  160. if( tld == 0 )
  161. {
  162. // Create a new tld
  163. tld = asNEW(asCThreadLocalData)();
  164. SetLocalData(id, tld);
  165. }
  166. return tld;
  167. #else
  168. if( tld == 0 )
  169. tld = asNEW(asCThreadLocalData)();
  170. return tld;
  171. #endif
  172. }
  173. //=========================================================================
  174. asCThreadLocalData::asCThreadLocalData()
  175. {
  176. }
  177. asCThreadLocalData::~asCThreadLocalData()
  178. {
  179. }
  180. //=========================================================================
  181. #ifndef AS_NO_THREADS
  182. asCThreadCriticalSection::asCThreadCriticalSection()
  183. {
  184. #if defined AS_POSIX_THREADS
  185. pthread_mutex_init(&criticalSection, 0);
  186. #elif defined AS_WINDOWS_THREADS
  187. InitializeCriticalSection(&criticalSection);
  188. #endif
  189. }
  190. asCThreadCriticalSection::~asCThreadCriticalSection()
  191. {
  192. #if defined AS_POSIX_THREADS
  193. pthread_mutex_destroy(&criticalSection);
  194. #elif defined AS_WINDOWS_THREADS
  195. DeleteCriticalSection(&criticalSection);
  196. #endif
  197. }
  198. void asCThreadCriticalSection::Enter()
  199. {
  200. #if defined AS_POSIX_THREADS
  201. pthread_mutex_lock(&criticalSection);
  202. #elif defined AS_WINDOWS_THREADS
  203. EnterCriticalSection(&criticalSection);
  204. #endif
  205. }
  206. void asCThreadCriticalSection::Leave()
  207. {
  208. #if defined AS_POSIX_THREADS
  209. pthread_mutex_unlock(&criticalSection);
  210. #elif defined AS_WINDOWS_THREADS
  211. LeaveCriticalSection(&criticalSection);
  212. #endif
  213. }
  214. bool asCThreadCriticalSection::TryEnter()
  215. {
  216. #if defined AS_POSIX_THREADS
  217. return !pthread_mutex_trylock(&criticalSection);
  218. #elif defined AS_WINDOWS_THREADS
  219. return TryEnterCriticalSection(&criticalSection) ? true : false;
  220. #else
  221. return true;
  222. #endif
  223. }
  224. #endif
  225. //========================================================================
  226. END_AS_NAMESPACE