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 intrusive_ptr_add_ref(thread_data_base * p)148 friend void intrusive_ptr_add_ref(thread_data_base * p) 149 { 150 BOOST_INTERLOCKED_INCREMENT(&p->count); 151 } 152 intrusive_ptr_release(thread_data_base * p)153 friend void intrusive_ptr_release(thread_data_base * p) 154 { 155 if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) 156 { 157 detail::heap_delete(p); 158 } 159 } 160 161 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS interruptboost::detail::thread_data_base162 void interrupt() 163 { 164 BOOST_VERIFY(winapi::SetEvent(interruption_handle)!=0); 165 } 166 #endif 167 typedef detail::win32::handle native_handle_type; 168 169 virtual void run()=0; 170 notify_all_at_thread_exitboost::detail::thread_data_base171 virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) 172 { 173 notify.push_back(std::pair<condition_variable*, mutex*>(cv, m)); 174 } 175 176 //#ifndef BOOST_NO_EXCEPTIONS make_ready_at_thread_exitboost::detail::thread_data_base177 void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) 178 { 179 async_states_.push_back(as); 180 } 181 //#endif 182 }; 183 BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); 184 185 typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr; 186 } 187 188 namespace this_thread 189 { 190 void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; 191 192 bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout); 193 194 #if defined BOOST_THREAD_USES_DATETIME 195 template<typename TimeDuration> sleep(TimeDuration const & rel_time)196 BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) 197 { 198 interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time)); 199 } 200 sleep(system_time const & abs_time)201 inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) 202 { 203 const detail::real_platform_timepoint ts(abs_time); 204 detail::platform_duration d(ts - detail::real_platform_clock::now()); 205 while (d > detail::platform_duration::zero()) 206 { 207 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)); 208 interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d); 209 d = ts - detail::real_platform_clock::now(); 210 } 211 } 212 #endif 213 214 #ifdef BOOST_THREAD_USES_CHRONO 215 template <class Rep, class Period> sleep_for(const chrono::duration<Rep,Period> & d)216 void sleep_for(const chrono::duration<Rep, Period>& d) 217 { 218 interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d)); 219 } 220 221 template <class Duration> sleep_until(const chrono::time_point<chrono::steady_clock,Duration> & t)222 void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t) 223 { 224 sleep_for(t - chrono::steady_clock::now()); 225 } 226 227 template <class Clock, class Duration> sleep_until(const chrono::time_point<Clock,Duration> & t)228 void sleep_until(const chrono::time_point<Clock, Duration>& t) 229 { 230 typedef typename common_type<Duration, typename Clock::duration>::type common_duration; 231 common_duration d(t - Clock::now()); 232 while (d > common_duration::zero()) 233 { 234 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS))); 235 sleep_for(d); 236 d = t - Clock::now(); 237 } 238 } 239 #endif 240 241 namespace no_interruption_point 242 { 243 bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout); 244 245 #if defined BOOST_THREAD_USES_DATETIME 246 template<typename TimeDuration> sleep(TimeDuration const & rel_time)247 BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) 248 { 249 non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time)); 250 } 251 sleep(system_time const & abs_time)252 inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) 253 { 254 const detail::real_platform_timepoint ts(abs_time); 255 detail::platform_duration d(ts - detail::real_platform_clock::now()); 256 while (d > detail::platform_duration::zero()) 257 { 258 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)); 259 non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d); 260 d = ts - detail::real_platform_clock::now(); 261 } 262 } 263 #endif 264 265 #ifdef BOOST_THREAD_USES_CHRONO 266 template <class Rep, class Period> sleep_for(const chrono::duration<Rep,Period> & d)267 void sleep_for(const chrono::duration<Rep, Period>& d) 268 { 269 non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d)); 270 } 271 272 template <class Duration> sleep_until(const chrono::time_point<chrono::steady_clock,Duration> & t)273 void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t) 274 { 275 sleep_for(t - chrono::steady_clock::now()); 276 } 277 278 template <class Clock, class Duration> sleep_until(const chrono::time_point<Clock,Duration> & t)279 void sleep_until(const chrono::time_point<Clock, Duration>& t) 280 { 281 typedef typename common_type<Duration, typename Clock::duration>::type common_duration; 282 common_duration d(t - Clock::now()); 283 while (d > common_duration::zero()) 284 { 285 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS))); 286 sleep_for(d); 287 d = t - Clock::now(); 288 } 289 } 290 #endif 291 } 292 } 293 294 } 295 296 #ifdef BOOST_MSVC 297 #pragma warning(pop) 298 #endif 299 300 #include <boost/config/abi_suffix.hpp> 301 302 #endif 303