thread.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "platform.h"
  18. #include "mutex.h"
  19. #include "alloc.h"
  20. #include "vector.h"
  21. #include <vector>
  22. namespace embree
  23. {
  24. /*! type for thread */
  25. typedef struct opaque_thread_t* thread_t;
  26. /*! signature of thread start function */
  27. typedef void (*thread_func)(void*);
  28. /*! creates a hardware thread running on specific logical thread */
  29. thread_t createThread(thread_func f, void* arg, size_t stack_size = 0, ssize_t threadID = -1);
  30. /*! set affinity of the calling thread */
  31. void setAffinity(ssize_t affinity);
  32. /*! the thread calling this function gets yielded */
  33. void yield();
  34. /*! waits until the given thread has terminated */
  35. void join(thread_t tid);
  36. /*! destroy handle of a thread */
  37. void destroyThread(thread_t tid);
  38. /*! type for handle to thread local storage */
  39. typedef struct opaque_tls_t* tls_t;
  40. /*! creates thread local storage */
  41. tls_t createTls();
  42. /*! set the thread local storage pointer */
  43. void setTls(tls_t tls, void* const ptr);
  44. /*! return the thread local storage pointer */
  45. void* getTls(tls_t tls);
  46. /*! destroys thread local storage identifier */
  47. void destroyTls(tls_t tls);
  48. /*! thread local storage implementation that supports arbirary number of thread locals */
  49. struct ThreadLocalStorage
  50. {
  51. struct ThreadLocal
  52. {
  53. public:
  54. ThreadLocal (size_t num)
  55. {
  56. ptrs.resize(num);
  57. for (size_t i=0; i<num; i++) ptrs[i] = nullptr;
  58. }
  59. __forceinline void init(size_t id)
  60. {
  61. if (likely(id < ptrs.size())) {
  62. ptrs[id] = nullptr;
  63. }
  64. else
  65. {
  66. Lock<SpinLock> lock(mutex);
  67. if (id >= ptrs.size()) ptrs.resize(id+1);
  68. ptrs[id] = nullptr;
  69. }
  70. }
  71. __forceinline void* get(size_t id)
  72. {
  73. Lock<SpinLock> lock(mutex);
  74. return ptrs[id];
  75. }
  76. __forceinline void set(size_t id, void* const ptr)
  77. {
  78. Lock<SpinLock> lock(mutex);
  79. ptrs[id] = ptr;
  80. }
  81. private:
  82. SpinLock mutex;
  83. avector<void*> ptrs;
  84. MAYBE_UNUSED char align[64];
  85. };
  86. ThreadLocalStorage()
  87. : key(createTls()) {}
  88. ~ThreadLocalStorage()
  89. {
  90. destroyTls(key);
  91. for (auto thread : threads)
  92. delete thread;
  93. }
  94. size_t create()
  95. {
  96. Lock<SpinLock> lock(mutex);
  97. size_t id = ids.allocate();
  98. for (auto thread : threads) thread->init(id);
  99. return id;
  100. }
  101. __forceinline void* get(size_t id) {
  102. return get_thread_local()->get(id);
  103. }
  104. __forceinline void set(size_t id, void* const ptr) {
  105. get_thread_local()->set(id,ptr);
  106. }
  107. void destroy(size_t id)
  108. {
  109. Lock<SpinLock> lock(mutex);
  110. ids.deallocate(id);
  111. }
  112. static __forceinline ThreadLocalStorage* instance() {
  113. return &single_instance;
  114. }
  115. private:
  116. __forceinline ThreadLocal* get_thread_local()
  117. {
  118. ThreadLocal* tls = (ThreadLocal*) getTls(key);
  119. if (unlikely(tls == nullptr)) {
  120. Lock<SpinLock> lock(mutex);
  121. tls = new ThreadLocal(ids.size());
  122. setTls(key,tls);
  123. threads.push_back(tls);
  124. }
  125. return tls;
  126. }
  127. private:
  128. SpinLock mutex;
  129. IDPool<size_t> ids;
  130. tls_t key;
  131. std::vector<ThreadLocal*> threads;
  132. static ThreadLocalStorage single_instance;
  133. };
  134. #if 0
  135. /*! manages thread local variables */
  136. template<typename Type, typename InitType>
  137. struct ThreadLocalData
  138. {
  139. public:
  140. __forceinline ThreadLocalData (InitType init)
  141. : ptr(-1), init(init) {}
  142. __forceinline ~ThreadLocalData () {
  143. clear();
  144. }
  145. __forceinline void clear()
  146. {
  147. if (ptr != -1) ThreadLocalStorage::instance()->destroy(ptr); ptr = -1;
  148. for (size_t i=0; i<threads.size(); i++)
  149. delete threads[i];
  150. threads.clear();
  151. }
  152. /*! disallow copy */
  153. ThreadLocalData(const ThreadLocalData&) DELETED;
  154. ThreadLocalData& operator=(const ThreadLocalData&) DELETED;
  155. template<typename Closure>
  156. __forceinline void apply(const Closure& closure)
  157. {
  158. for (size_t i=0; i<threads.size(); i++)
  159. closure(threads[i]);
  160. }
  161. __forceinline Type* get() const
  162. {
  163. if (ptr == -1) {
  164. Lock<SpinLock> lock(mutex);
  165. if (ptr == -1) ptr = ThreadLocalStorage::instance()->create();
  166. }
  167. Type* lptr = (Type*) ThreadLocalStorage::instance()->get(ptr);
  168. if (lptr) return lptr;
  169. lptr = new Type(init);
  170. ThreadLocalStorage::instance()->set(ptr,lptr);
  171. Lock<SpinLock> lock(mutex);
  172. threads.push_back(lptr);
  173. return lptr;
  174. }
  175. __forceinline const Type& operator *( void ) const { return *get(); }
  176. __forceinline Type& operator *( void ) { return *get(); }
  177. __forceinline const Type* operator ->( void ) const { return get(); }
  178. __forceinline Type* operator ->( void ) { return get(); }
  179. private:
  180. mutable size_t ptr;
  181. InitType init;
  182. mutable SpinLock mutex;
  183. public:
  184. mutable std::vector<Type*> threads;
  185. };
  186. #else
  187. /*! manages thread local variables */
  188. template<typename Type, typename InitType>
  189. struct ThreadLocalData
  190. {
  191. public:
  192. __forceinline ThreadLocalData (InitType init)
  193. : ptr(nullptr), init(init) {}
  194. __forceinline ~ThreadLocalData () {
  195. clear();
  196. }
  197. __forceinline void clear()
  198. {
  199. if (ptr) destroyTls(ptr); ptr = nullptr;
  200. for (size_t i=0; i<threads.size(); i++)
  201. delete threads[i];
  202. threads.clear();
  203. }
  204. /*! disallow copy */
  205. ThreadLocalData(const ThreadLocalData&) DELETED;
  206. ThreadLocalData& operator=(const ThreadLocalData&) DELETED;
  207. template<typename Closure>
  208. __forceinline void apply(const Closure& closure)
  209. {
  210. for (size_t i=0; i<threads.size(); i++)
  211. closure(threads[i]);
  212. }
  213. __forceinline Type* get() const
  214. {
  215. if (ptr == nullptr) {
  216. Lock<SpinLock> lock(mutex);
  217. if (ptr == nullptr) ptr = createTls();
  218. }
  219. Type* lptr = (Type*) getTls(ptr);
  220. if (lptr) return lptr;
  221. lptr = new Type(init);
  222. setTls(ptr,lptr);
  223. Lock<SpinLock> lock(mutex);
  224. threads.push_back(lptr);
  225. return lptr;
  226. }
  227. __forceinline const Type& operator *( void ) const { return *get(); }
  228. __forceinline Type& operator *( void ) { return *get(); }
  229. __forceinline const Type* operator ->( void ) const { return get(); }
  230. __forceinline Type* operator ->( void ) { return get(); }
  231. private:
  232. mutable tls_t ptr;
  233. InitType init;
  234. mutable SpinLock mutex;
  235. public:
  236. mutable std::vector<Type*> threads;
  237. };
  238. #endif
  239. }