thread_data.hpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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/intrusive_ptr.hpp>
  13. #ifdef BOOST_THREAD_USES_CHRONO
  14. #include <boost/chrono/system_clocks.hpp>
  15. #endif
  16. #include <map>
  17. #include <vector>
  18. #include <utility>
  19. #include <boost/config/abi_prefix.hpp>
  20. #ifdef BOOST_MSVC
  21. #pragma warning(push)
  22. #pragma warning(disable:4251)
  23. #endif
  24. namespace boost
  25. {
  26. class condition_variable;
  27. class mutex;
  28. class thread_attributes {
  29. public:
  30. thread_attributes() BOOST_NOEXCEPT {
  31. val_.stack_size = 0;
  32. //val_.lpThreadAttributes=0;
  33. }
  34. ~thread_attributes() {
  35. }
  36. // stack size
  37. void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
  38. val_.stack_size = size;
  39. }
  40. std::size_t get_stack_size() const BOOST_NOEXCEPT {
  41. return val_.stack_size;
  42. }
  43. //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes)
  44. //{
  45. // val_.lpThreadAttributes=lpThreadAttributes;
  46. //}
  47. //LPSECURITY_ATTRIBUTES get_security()
  48. //{
  49. // return val_.lpThreadAttributes;
  50. //}
  51. struct win_attrs {
  52. std::size_t stack_size;
  53. //LPSECURITY_ATTRIBUTES lpThreadAttributes;
  54. };
  55. typedef win_attrs native_handle_type;
  56. native_handle_type* native_handle() {return &val_;}
  57. const native_handle_type* native_handle() const {return &val_;}
  58. private:
  59. win_attrs val_;
  60. };
  61. namespace detail
  62. {
  63. struct shared_state_base;
  64. struct tss_cleanup_function;
  65. struct thread_exit_callback_node;
  66. struct tss_data_node
  67. {
  68. boost::shared_ptr<boost::detail::tss_cleanup_function> func;
  69. void* value;
  70. tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
  71. void* value_):
  72. func(func_),value(value_)
  73. {}
  74. };
  75. struct thread_data_base;
  76. void intrusive_ptr_add_ref(thread_data_base * p);
  77. void intrusive_ptr_release(thread_data_base * p);
  78. struct BOOST_THREAD_DECL thread_data_base
  79. {
  80. long count;
  81. detail::win32::handle_manager thread_handle;
  82. boost::detail::thread_exit_callback_node* thread_exit_callbacks;
  83. std::map<void const*,boost::detail::tss_data_node> tss_data;
  84. unsigned id;
  85. typedef std::vector<std::pair<condition_variable*, mutex*>
  86. //, hidden_allocator<std::pair<condition_variable*, mutex*> >
  87. > notify_list_t;
  88. notify_list_t notify;
  89. typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
  90. async_states_t async_states_;
  91. //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  92. // These data must be at the end so that the access to the other fields doesn't change
  93. // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined
  94. // Another option is to have them always
  95. detail::win32::handle_manager interruption_handle;
  96. bool interruption_enabled;
  97. //#endif
  98. thread_data_base():
  99. count(0),thread_handle(detail::win32::invalid_handle_value),
  100. thread_exit_callbacks(0),tss_data(),
  101. id(0),
  102. notify(),
  103. async_states_()
  104. //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  105. , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset))
  106. , interruption_enabled(true)
  107. //#endif
  108. {}
  109. virtual ~thread_data_base();
  110. friend void intrusive_ptr_add_ref(thread_data_base * p)
  111. {
  112. BOOST_INTERLOCKED_INCREMENT(&p->count);
  113. }
  114. friend void intrusive_ptr_release(thread_data_base * p)
  115. {
  116. if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
  117. {
  118. detail::heap_delete(p);
  119. }
  120. }
  121. #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  122. void interrupt()
  123. {
  124. BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
  125. }
  126. #endif
  127. typedef detail::win32::handle native_handle_type;
  128. virtual void run()=0;
  129. virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
  130. {
  131. notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
  132. }
  133. void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
  134. {
  135. async_states_.push_back(as);
  136. }
  137. };
  138. BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
  139. typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
  140. struct BOOST_SYMBOL_VISIBLE timeout
  141. {
  142. win32::ticks_type start;
  143. uintmax_t milliseconds;
  144. bool relative;
  145. boost::system_time abs_time;
  146. static unsigned long const max_non_infinite_wait=0xfffffffe;
  147. timeout(uintmax_t milliseconds_):
  148. start(win32::GetTickCount64()),
  149. milliseconds(milliseconds_),
  150. relative(true),
  151. abs_time(boost::get_system_time())
  152. {}
  153. timeout(boost::system_time const& abs_time_):
  154. start(win32::GetTickCount64()),
  155. milliseconds(0),
  156. relative(false),
  157. abs_time(abs_time_)
  158. {}
  159. struct BOOST_SYMBOL_VISIBLE remaining_time
  160. {
  161. bool more;
  162. unsigned long milliseconds;
  163. remaining_time(uintmax_t remaining):
  164. more(remaining>max_non_infinite_wait),
  165. milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
  166. {}
  167. };
  168. remaining_time remaining_milliseconds() const
  169. {
  170. if(is_sentinel())
  171. {
  172. return remaining_time(win32::infinite);
  173. }
  174. else if(relative)
  175. {
  176. win32::ticks_type const now=win32::GetTickCount64();
  177. win32::ticks_type const elapsed=now-start;
  178. return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
  179. }
  180. else
  181. {
  182. system_time const now=get_system_time();
  183. if(abs_time<=now)
  184. {
  185. return remaining_time(0);
  186. }
  187. return remaining_time((abs_time-now).total_milliseconds()+1);
  188. }
  189. }
  190. bool is_sentinel() const
  191. {
  192. return milliseconds==~uintmax_t(0);
  193. }
  194. static timeout sentinel()
  195. {
  196. return timeout(sentinel_type());
  197. }
  198. private:
  199. struct sentinel_type
  200. {};
  201. explicit timeout(sentinel_type):
  202. start(0),milliseconds(~uintmax_t(0)),relative(true)
  203. {}
  204. };
  205. inline uintmax_t pin_to_zero(intmax_t value)
  206. {
  207. return (value<0)?0u:(uintmax_t)value;
  208. }
  209. }
  210. namespace this_thread
  211. {
  212. void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
  213. bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
  214. inline void interruptible_wait(uintmax_t milliseconds)
  215. {
  216. interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
  217. }
  218. inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time)
  219. {
  220. interruptible_wait(detail::win32::invalid_handle_value,abs_time);
  221. }
  222. template<typename TimeDuration>
  223. inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
  224. {
  225. interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
  226. }
  227. inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
  228. {
  229. interruptible_wait(abs_time);
  230. }
  231. #ifdef BOOST_THREAD_USES_CHRONO
  232. inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
  233. {
  234. interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
  235. }
  236. #endif
  237. }
  238. }
  239. #ifdef BOOST_MSVC
  240. #pragma warning(pop)
  241. #endif
  242. #include <boost/config/abi_suffix.hpp>
  243. #endif