thread_data.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. #ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
  2. #define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // (C) Copyright 2008 Anthony Williams
  7. // (C) Copyright 2011-2012 Vicente J. Botet Escriba
  8. #include <boost/thread/detail/config.hpp>
  9. #include <boost/thread/thread_time.hpp>
  10. #include <boost/thread/win32/thread_primitives.hpp>
  11. #include <boost/thread/win32/thread_heap_alloc.hpp>
  12. #include <boost/predef/platform.h>
  13. #include <boost/intrusive_ptr.hpp>
  14. #ifdef BOOST_THREAD_USES_CHRONO
  15. #include <boost/chrono/system_clocks.hpp>
  16. #endif
  17. #include <map>
  18. #include <vector>
  19. #include <utility>
  20. #include <boost/config/abi_prefix.hpp>
  21. #ifdef BOOST_MSVC
  22. #pragma warning(push)
  23. #pragma warning(disable:4251)
  24. #endif
  25. namespace boost
  26. {
  27. class condition_variable;
  28. class mutex;
  29. class thread_attributes {
  30. public:
  31. thread_attributes() BOOST_NOEXCEPT {
  32. val_.stack_size = 0;
  33. //val_.lpThreadAttributes=0;
  34. }
  35. ~thread_attributes() {
  36. }
  37. // stack size
  38. void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
  39. val_.stack_size = size;
  40. }
  41. std::size_t get_stack_size() const BOOST_NOEXCEPT {
  42. return val_.stack_size;
  43. }
  44. //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes)
  45. //{
  46. // val_.lpThreadAttributes=lpThreadAttributes;
  47. //}
  48. //LPSECURITY_ATTRIBUTES get_security()
  49. //{
  50. // return val_.lpThreadAttributes;
  51. //}
  52. struct win_attrs {
  53. std::size_t stack_size;
  54. //LPSECURITY_ATTRIBUTES lpThreadAttributes;
  55. };
  56. typedef win_attrs native_handle_type;
  57. native_handle_type* native_handle() {return &val_;}
  58. const native_handle_type* native_handle() const {return &val_;}
  59. private:
  60. win_attrs val_;
  61. };
  62. namespace detail
  63. {
  64. struct shared_state_base;
  65. struct tss_cleanup_function;
  66. struct thread_exit_callback_node;
  67. struct tss_data_node
  68. {
  69. boost::shared_ptr<boost::detail::tss_cleanup_function> func;
  70. void* value;
  71. tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
  72. void* value_):
  73. func(func_),value(value_)
  74. {}
  75. };
  76. struct thread_data_base;
  77. void intrusive_ptr_add_ref(thread_data_base * p);
  78. void intrusive_ptr_release(thread_data_base * p);
  79. struct BOOST_THREAD_DECL thread_data_base
  80. {
  81. long count;
  82. // Win32 threading APIs are not available in store apps so
  83. // use abstraction on top of Windows::System::Threading.
  84. #if BOOST_PLAT_WINDOWS_RUNTIME
  85. detail::win32::scoped_winrt_thread thread_handle;
  86. #else
  87. detail::win32::handle_manager thread_handle;
  88. #endif
  89. boost::detail::thread_exit_callback_node* thread_exit_callbacks;
  90. unsigned id;
  91. std::map<void const*,boost::detail::tss_data_node> tss_data;
  92. typedef std::vector<std::pair<condition_variable*, mutex*>
  93. //, hidden_allocator<std::pair<condition_variable*, mutex*> >
  94. > notify_list_t;
  95. notify_list_t notify;
  96. typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
  97. async_states_t async_states_;
  98. //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  99. // These data must be at the end so that the access to the other fields doesn't change
  100. // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined
  101. // Another option is to have them always
  102. detail::win32::handle_manager interruption_handle;
  103. bool interruption_enabled;
  104. //#endif
  105. thread_data_base():
  106. count(0),
  107. thread_handle(),
  108. thread_exit_callbacks(0),
  109. id(0),
  110. tss_data(),
  111. notify(),
  112. async_states_()
  113. //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  114. , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset))
  115. , interruption_enabled(true)
  116. //#endif
  117. {}
  118. virtual ~thread_data_base();
  119. friend void intrusive_ptr_add_ref(thread_data_base * p)
  120. {
  121. BOOST_INTERLOCKED_INCREMENT(&p->count);
  122. }
  123. friend void intrusive_ptr_release(thread_data_base * p)
  124. {
  125. if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
  126. {
  127. detail::heap_delete(p);
  128. }
  129. }
  130. #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  131. void interrupt()
  132. {
  133. BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
  134. }
  135. #endif
  136. typedef detail::win32::handle native_handle_type;
  137. virtual void run()=0;
  138. virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
  139. {
  140. notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
  141. }
  142. void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
  143. {
  144. async_states_.push_back(as);
  145. }
  146. };
  147. BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
  148. typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
  149. struct BOOST_SYMBOL_VISIBLE timeout
  150. {
  151. win32::ticks_type start;
  152. uintmax_t milliseconds;
  153. bool relative;
  154. boost::system_time abs_time;
  155. static unsigned long const max_non_infinite_wait=0xfffffffe;
  156. timeout(uintmax_t milliseconds_):
  157. start(win32::GetTickCount64_()()),
  158. milliseconds(milliseconds_),
  159. relative(true)
  160. //,
  161. // abs_time(boost::get_system_time())
  162. {}
  163. timeout(boost::system_time const& abs_time_):
  164. start(win32::GetTickCount64_()()),
  165. milliseconds(0),
  166. relative(false),
  167. abs_time(abs_time_)
  168. {}
  169. struct BOOST_SYMBOL_VISIBLE remaining_time
  170. {
  171. bool more;
  172. unsigned long milliseconds;
  173. remaining_time(uintmax_t remaining):
  174. more(remaining>max_non_infinite_wait),
  175. milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
  176. {}
  177. };
  178. remaining_time remaining_milliseconds() const
  179. {
  180. if(is_sentinel())
  181. {
  182. return remaining_time(win32::infinite);
  183. }
  184. else if(relative)
  185. {
  186. win32::ticks_type const now=win32::GetTickCount64_()();
  187. win32::ticks_type const elapsed=now-start;
  188. return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
  189. }
  190. else
  191. {
  192. system_time const now=get_system_time();
  193. if(abs_time<=now)
  194. {
  195. return remaining_time(0);
  196. }
  197. return remaining_time((abs_time-now).total_milliseconds()+1);
  198. }
  199. }
  200. bool is_sentinel() const
  201. {
  202. return milliseconds==~uintmax_t(0);
  203. }
  204. static timeout sentinel()
  205. {
  206. return timeout(sentinel_type());
  207. }
  208. private:
  209. struct sentinel_type
  210. {};
  211. explicit timeout(sentinel_type):
  212. start(0),milliseconds(~uintmax_t(0)),relative(true)
  213. {}
  214. };
  215. inline uintmax_t pin_to_zero(intmax_t value)
  216. {
  217. return (value<0)?0u:(uintmax_t)value;
  218. }
  219. }
  220. namespace this_thread
  221. {
  222. void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
  223. bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
  224. inline void interruptible_wait(uintmax_t milliseconds)
  225. {
  226. interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
  227. }
  228. inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time)
  229. {
  230. interruptible_wait(detail::win32::invalid_handle_value,abs_time);
  231. }
  232. template<typename TimeDuration>
  233. inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
  234. {
  235. interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
  236. }
  237. inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
  238. {
  239. interruptible_wait(abs_time);
  240. }
  241. // #11322 sleep_for() nanoseconds overload will always return too early on windows
  242. //#ifdef BOOST_THREAD_USES_CHRONO
  243. // inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
  244. // {
  245. // interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
  246. // }
  247. //#endif
  248. namespace no_interruption_point
  249. {
  250. bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
  251. inline void non_interruptible_wait(uintmax_t milliseconds)
  252. {
  253. non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
  254. }
  255. inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time)
  256. {
  257. non_interruptible_wait(detail::win32::invalid_handle_value,abs_time);
  258. }
  259. template<typename TimeDuration>
  260. inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
  261. {
  262. non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
  263. }
  264. inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
  265. {
  266. non_interruptible_wait(abs_time);
  267. }
  268. // #11322 sleep_for() nanoseconds overload will always return too early on windows
  269. //#ifdef BOOST_THREAD_USES_CHRONO
  270. // inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
  271. // {
  272. // non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
  273. // }
  274. //#endif
  275. }
  276. }
  277. }
  278. #ifdef BOOST_MSVC
  279. #pragma warning(pop)
  280. #endif
  281. #include <boost/config/abi_suffix.hpp>
  282. #endif