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 9 #include <boost/thread/detail/config.hpp> 10 #include <boost/thread/thread_time.hpp> 11 #include <boost/thread/win32/thread_primitives.hpp> 12 #include <boost/thread/win32/thread_heap_alloc.hpp> 13 #include <boost/thread/detail/platform_time.hpp> 14 15 #include <boost/predef/platform.h> 16 17 #include <boost/intrusive_ptr.hpp> 18 #ifdef BOOST_THREAD_USES_CHRONO 19 #include <boost/chrono/system_clocks.hpp> 20 #endif 21 22 #include <map> 23 #include <vector> 24 #include <utility> 25 26 #include <boost/config/abi_prefix.hpp> 27 28 #ifdef BOOST_MSVC 29 #pragma warning(push) 30 #pragma warning(disable:4251) 31 #endif 32 33 namespace boost 34 { 35 class condition_variable; 36 class mutex; 37 38 class thread_attributes { 39 public: thread_attributes()40 thread_attributes() BOOST_NOEXCEPT { 41 val_.stack_size = 0; 42 //val_.lpThreadAttributes=0; 43 } ~thread_attributes()44 ~thread_attributes() { 45 } 46 // stack size set_stack_size(std::size_t size)47 void set_stack_size(std::size_t size) BOOST_NOEXCEPT { 48 val_.stack_size = size; 49 } 50 get_stack_size() const51 std::size_t get_stack_size() const BOOST_NOEXCEPT { 52 return val_.stack_size; 53 } 54 55 //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes) 56 //{ 57 // val_.lpThreadAttributes=lpThreadAttributes; 58 //} 59 //LPSECURITY_ATTRIBUTES get_security() 60 //{ 61 // return val_.lpThreadAttributes; 62 //} 63 64 struct win_attrs { 65 std::size_t stack_size; 66 //LPSECURITY_ATTRIBUTES lpThreadAttributes; 67 }; 68 typedef win_attrs native_handle_type; native_handle()69 native_handle_type* native_handle() {return &val_;} native_handle() const70 const native_handle_type* native_handle() const {return &val_;} 71 72 private: 73 win_attrs val_; 74 }; 75 76 namespace detail 77 { 78 struct shared_state_base; 79 struct tss_cleanup_function; 80 struct thread_exit_callback_node; 81 struct tss_data_node 82 { 83 typedef void(*cleanup_func_t)(void*); 84 typedef void(*cleanup_caller_t)(cleanup_func_t, void*); 85 86 cleanup_caller_t caller; 87 cleanup_func_t func; 88 void* value; 89 tss_data_nodeboost::detail::tss_data_node90 tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_): 91 caller(caller_),func(func_),value(value_) 92 {} 93 }; 94 95 struct thread_data_base; 96 void intrusive_ptr_add_ref(thread_data_base * p); 97 void intrusive_ptr_release(thread_data_base * p); 98 99 struct BOOST_THREAD_DECL thread_data_base 100 { 101 long count; 102 103 // Win32 threading APIs are not available in store apps so 104 // use abstraction on top of Windows::System::Threading. 105 #if BOOST_PLAT_WINDOWS_RUNTIME 106 detail::win32::scoped_winrt_thread thread_handle; 107 #else 108 detail::win32::handle_manager thread_handle; 109 #endif 110 111 boost::detail::thread_exit_callback_node* thread_exit_callbacks; 112 unsigned id; 113 std::map<void const*,boost::detail::tss_data_node> tss_data; 114 typedef std::vector<std::pair<condition_variable*, mutex*> 115 //, hidden_allocator<std::pair<condition_variable*, mutex*> > 116 > notify_list_t; 117 notify_list_t notify; 118 119 //#ifndef BOOST_NO_EXCEPTIONS 120 typedef std::vector<shared_ptr<shared_state_base> > async_states_t; 121 async_states_t async_states_; 122 //#endif 123 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 124 // These data must be at the end so that the access to the other fields doesn't change 125 // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined 126 // Another option is to have them always 127 detail::win32::handle_manager interruption_handle; 128 bool interruption_enabled; 129 //#endif 130 thread_data_baseboost::detail::thread_data_base131 thread_data_base(): 132 count(0), 133 thread_handle(), 134 thread_exit_callbacks(0), 135 id(0), 136 tss_data(), 137 notify() 138 //#ifndef BOOST_NO_EXCEPTIONS 139 , async_states_() 140 //#endif 141 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 142 , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)) 143 , interruption_enabled(true) 144 //#endif 145 {} 146 virtual ~thread_data_base(); 147 148 #if !defined(BOOST_EMBTC) 149 intrusive_ptr_add_ref(thread_data_base * p)150 friend void intrusive_ptr_add_ref(thread_data_base * p) 151 { 152 BOOST_INTERLOCKED_INCREMENT(&p->count); 153 } 154 intrusive_ptr_release(thread_data_base * p)155 friend void intrusive_ptr_release(thread_data_base * p) 156 { 157 if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) 158 { 159 detail::heap_delete(p); 160 } 161 } 162 163 #else 164 165 friend void intrusive_ptr_add_ref(thread_data_base * p); 166 friend void intrusive_ptr_release(thread_data_base * p); 167 168 #endif 169 170 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS interruptboost::detail::thread_data_base171 void interrupt() 172 { 173 BOOST_VERIFY(winapi::SetEvent(interruption_handle)!=0); 174 } 175 #endif 176 typedef detail::win32::handle native_handle_type; 177 178 virtual void run()=0; 179 notify_all_at_thread_exitboost::detail::thread_data_base180 virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) 181 { 182 notify.push_back(std::pair<condition_variable*, mutex*>(cv, m)); 183 } 184 185 //#ifndef BOOST_NO_EXCEPTIONS make_ready_at_thread_exitboost::detail::thread_data_base186 void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) 187 { 188 async_states_.push_back(as); 189 } 190 //#endif 191 }; 192 193 #if defined(BOOST_EMBTC) 194 intrusive_ptr_add_ref(thread_data_base * p)195 inline void intrusive_ptr_add_ref(thread_data_base * p) 196 { 197 BOOST_INTERLOCKED_INCREMENT(&p->count); 198 } 199 intrusive_ptr_release(thread_data_base * p)200 inline void intrusive_ptr_release(thread_data_base * p) 201 { 202 if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) 203 { 204 detail::heap_delete(p); 205 } 206 } 207 208 #endif 209 210 BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); 211 212 typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr; 213 } 214 215 namespace this_thread 216 { 217 void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; 218 219 bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout); 220 221 #if defined BOOST_THREAD_USES_DATETIME 222 template<typename TimeDuration> sleep(TimeDuration const & rel_time)223 BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) 224 { 225 interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time)); 226 } 227 sleep(system_time const & abs_time)228 inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) 229 { 230 const detail::real_platform_timepoint ts(abs_time); 231 detail::platform_duration d(ts - detail::real_platform_clock::now()); 232 while (d > detail::platform_duration::zero()) 233 { 234 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)); 235 interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d); 236 d = ts - detail::real_platform_clock::now(); 237 } 238 } 239 #endif 240 241 #ifdef BOOST_THREAD_USES_CHRONO 242 template <class Rep, class Period> sleep_for(const chrono::duration<Rep,Period> & d)243 void sleep_for(const chrono::duration<Rep, Period>& d) 244 { 245 interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d)); 246 } 247 248 template <class Duration> sleep_until(const chrono::time_point<chrono::steady_clock,Duration> & t)249 void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t) 250 { 251 sleep_for(t - chrono::steady_clock::now()); 252 } 253 254 template <class Clock, class Duration> sleep_until(const chrono::time_point<Clock,Duration> & t)255 void sleep_until(const chrono::time_point<Clock, Duration>& t) 256 { 257 typedef typename common_type<Duration, typename Clock::duration>::type common_duration; 258 common_duration d(t - Clock::now()); 259 while (d > common_duration::zero()) 260 { 261 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS))); 262 sleep_for(d); 263 d = t - Clock::now(); 264 } 265 } 266 #endif 267 268 namespace no_interruption_point 269 { 270 bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout); 271 272 #if defined BOOST_THREAD_USES_DATETIME 273 template<typename TimeDuration> sleep(TimeDuration const & rel_time)274 BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) 275 { 276 non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time)); 277 } 278 sleep(system_time const & abs_time)279 inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) 280 { 281 const detail::real_platform_timepoint ts(abs_time); 282 detail::platform_duration d(ts - detail::real_platform_clock::now()); 283 while (d > detail::platform_duration::zero()) 284 { 285 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)); 286 non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d); 287 d = ts - detail::real_platform_clock::now(); 288 } 289 } 290 #endif 291 292 #ifdef BOOST_THREAD_USES_CHRONO 293 template <class Rep, class Period> sleep_for(const chrono::duration<Rep,Period> & d)294 void sleep_for(const chrono::duration<Rep, Period>& d) 295 { 296 non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d)); 297 } 298 299 template <class Duration> sleep_until(const chrono::time_point<chrono::steady_clock,Duration> & t)300 void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t) 301 { 302 sleep_for(t - chrono::steady_clock::now()); 303 } 304 305 template <class Clock, class Duration> sleep_until(const chrono::time_point<Clock,Duration> & t)306 void sleep_until(const chrono::time_point<Clock, Duration>& t) 307 { 308 typedef typename common_type<Duration, typename Clock::duration>::type common_duration; 309 common_duration d(t - Clock::now()); 310 while (d > common_duration::zero()) 311 { 312 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS))); 313 sleep_for(d); 314 d = t - Clock::now(); 315 } 316 } 317 #endif 318 } 319 } 320 321 } 322 323 #ifdef BOOST_MSVC 324 #pragma warning(pop) 325 #endif 326 327 #include <boost/config/abi_suffix.hpp> 328 329 #endif 330