File indexing completed on 2025-12-16 10:10:02
0001 #ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
0002 #define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
0003
0004
0005
0006
0007
0008
0009 #include <boost/thread/detail/config.hpp>
0010 #include <boost/thread/exceptions.hpp>
0011 #include <boost/thread/lock_guard.hpp>
0012 #include <boost/thread/lock_types.hpp>
0013 #include <boost/thread/mutex.hpp>
0014 #include <boost/thread/pthread/condition_variable_fwd.hpp>
0015 #include <boost/thread/pthread/pthread_helpers.hpp>
0016
0017 #include <boost/shared_ptr.hpp>
0018 #include <boost/enable_shared_from_this.hpp>
0019 #include <boost/assert.hpp>
0020 #include <boost/thread/detail/platform_time.hpp>
0021 #ifdef BOOST_THREAD_USES_CHRONO
0022 #include <boost/chrono/system_clocks.hpp>
0023 #endif
0024
0025 #include <map>
0026 #include <vector>
0027 #include <utility>
0028
0029 #if defined(__ANDROID__)
0030 # ifndef PAGE_SIZE
0031 # define PAGE_SIZE 4096
0032 # endif
0033 #endif
0034
0035 #include <pthread.h>
0036 #include <unistd.h>
0037
0038 #include <boost/config/abi_prefix.hpp>
0039
0040 namespace boost
0041 {
0042 class thread_attributes {
0043 public:
0044 thread_attributes() BOOST_NOEXCEPT {
0045 int res = pthread_attr_init(&val_);
0046 BOOST_VERIFY(!res && "pthread_attr_init failed");
0047 }
0048 ~thread_attributes() {
0049 int res = pthread_attr_destroy(&val_);
0050 BOOST_VERIFY(!res && "pthread_attr_destroy failed");
0051 }
0052
0053 void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
0054 if (size==0) return;
0055 #ifdef BOOST_THREAD_USES_GETPAGESIZE
0056 std::size_t page_size = getpagesize();
0057 #else
0058 std::size_t page_size = ::sysconf( _SC_PAGESIZE);
0059 #endif
0060 #ifdef PTHREAD_STACK_MIN
0061 if (size<static_cast<std::size_t>(PTHREAD_STACK_MIN)) size=PTHREAD_STACK_MIN;
0062 #endif
0063 size = ((size+page_size-1)/page_size)*page_size;
0064 int res = pthread_attr_setstacksize(&val_, size);
0065 BOOST_VERIFY(!res && "pthread_attr_setstacksize failed");
0066 }
0067
0068 std::size_t get_stack_size() const BOOST_NOEXCEPT {
0069 std::size_t size;
0070 int res = pthread_attr_getstacksize(&val_, &size);
0071 BOOST_VERIFY(!res && "pthread_attr_getstacksize failed");
0072 return size;
0073 }
0074 #define BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE
0075
0076 typedef pthread_attr_t native_handle_type;
0077 native_handle_type* native_handle() BOOST_NOEXCEPT {
0078 return &val_;
0079 }
0080 const native_handle_type* native_handle() const BOOST_NOEXCEPT {
0081 return &val_;
0082 }
0083
0084 private:
0085 pthread_attr_t val_;
0086 };
0087
0088 class thread;
0089
0090 namespace detail
0091 {
0092 struct shared_state_base;
0093 struct tss_cleanup_function;
0094 struct thread_exit_callback_node;
0095 struct tss_data_node
0096 {
0097 typedef void(*cleanup_func_t)(void*);
0098 typedef void(*cleanup_caller_t)(cleanup_func_t, void*);
0099
0100 cleanup_caller_t caller;
0101 cleanup_func_t func;
0102 void* value;
0103
0104 tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_):
0105 caller(caller_),func(func_),value(value_)
0106 {}
0107 };
0108
0109 struct thread_data_base;
0110 typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
0111
0112 struct BOOST_THREAD_DECL thread_data_base:
0113 enable_shared_from_this<thread_data_base>
0114 {
0115 thread_data_ptr self;
0116 pthread_t thread_handle;
0117 boost::mutex data_mutex;
0118 boost::condition_variable done_condition;
0119 bool done;
0120 bool join_started;
0121 bool joined;
0122 boost::detail::thread_exit_callback_node* thread_exit_callbacks;
0123 std::map<void const*,boost::detail::tss_data_node> tss_data;
0124
0125
0126
0127
0128
0129 pthread_mutex_t* cond_mutex;
0130 pthread_cond_t* current_cond;
0131
0132 typedef std::vector<std::pair<condition_variable*, mutex*>
0133
0134 > notify_list_t;
0135 notify_list_t notify;
0136
0137
0138 typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
0139 async_states_t async_states_;
0140
0141
0142
0143
0144
0145 bool interrupt_enabled;
0146 bool interrupt_requested;
0147
0148 thread_data_base():
0149 thread_handle(0),
0150 done(false),join_started(false),joined(false),
0151 thread_exit_callbacks(0),
0152
0153 cond_mutex(0),
0154 current_cond(0),
0155
0156 notify()
0157
0158 , async_states_()
0159
0160
0161 , interrupt_enabled(true)
0162 , interrupt_requested(false)
0163
0164 {}
0165 virtual ~thread_data_base();
0166
0167 typedef pthread_t native_handle_type;
0168
0169 virtual void run()=0;
0170 virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
0171 {
0172 notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
0173 }
0174
0175
0176 void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
0177 {
0178 async_states_.push_back(as);
0179 }
0180
0181 };
0182
0183 BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
0184
0185 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0186 class interruption_checker
0187 {
0188 thread_data_base* const thread_info;
0189 pthread_mutex_t* m;
0190 bool set;
0191 bool done;
0192
0193 void check_for_interruption()
0194 {
0195 #ifndef BOOST_NO_EXCEPTIONS
0196 if(thread_info->interrupt_requested)
0197 {
0198 thread_info->interrupt_requested=false;
0199 throw thread_interrupted();
0200 }
0201 #endif
0202 }
0203
0204 void operator=(interruption_checker&);
0205 public:
0206 explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
0207 thread_info(detail::get_current_thread_data()),m(cond_mutex),
0208 set(thread_info && thread_info->interrupt_enabled), done(false)
0209 {
0210 if(set)
0211 {
0212 lock_guard<mutex> guard(thread_info->data_mutex);
0213 check_for_interruption();
0214 thread_info->cond_mutex=cond_mutex;
0215 thread_info->current_cond=cond;
0216 BOOST_VERIFY(!posix::pthread_mutex_lock(m));
0217 }
0218 else
0219 {
0220 BOOST_VERIFY(!posix::pthread_mutex_lock(m));
0221 }
0222 }
0223 void unlock_if_locked()
0224 {
0225 if ( ! done) {
0226 if (set)
0227 {
0228 BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
0229 lock_guard<mutex> guard(thread_info->data_mutex);
0230 thread_info->cond_mutex=NULL;
0231 thread_info->current_cond=NULL;
0232 }
0233 else
0234 {
0235 BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
0236 }
0237 done = true;
0238 }
0239 }
0240
0241 ~interruption_checker() BOOST_NOEXCEPT_IF(false)
0242 {
0243 unlock_if_locked();
0244 }
0245 };
0246 #endif
0247 }
0248
0249 namespace this_thread
0250 {
0251 void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
0252
0253 namespace hidden
0254 {
0255 inline bool always_false()
0256 {
0257 return false;
0258 }
0259 }
0260
0261 #if defined BOOST_THREAD_USES_DATETIME
0262 #ifdef __DECXXX
0263
0264 template<>
0265 #endif
0266 inline void sleep(system_time const& abs_time)
0267 {
0268 mutex mx;
0269 unique_lock<mutex> lock(mx);
0270 condition_variable cond;
0271 cond.timed_wait(lock, abs_time, hidden::always_false);
0272 }
0273
0274 template<typename TimeDuration>
0275 void sleep(TimeDuration const& rel_time)
0276 {
0277 mutex mx;
0278 unique_lock<mutex> lock(mx);
0279 condition_variable cond;
0280 cond.timed_wait(lock, rel_time, hidden::always_false);
0281 }
0282 #endif
0283
0284 #ifdef BOOST_THREAD_USES_CHRONO
0285 template <class Clock, class Duration>
0286 void sleep_until(const chrono::time_point<Clock, Duration>& t)
0287 {
0288 mutex mut;
0289 unique_lock<mutex> lk(mut);
0290 condition_variable cv;
0291 cv.wait_until(lk, t, hidden::always_false);
0292 }
0293
0294 template <class Rep, class Period>
0295 void sleep_for(const chrono::duration<Rep, Period>& d)
0296 {
0297 mutex mut;
0298 unique_lock<mutex> lk(mut);
0299 condition_variable cv;
0300 cv.wait_for(lk, d, hidden::always_false);
0301 }
0302 #endif
0303
0304 namespace no_interruption_point
0305 {
0306 #if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY
0307
0308
0309
0310 namespace hidden
0311 {
0312 void BOOST_THREAD_DECL sleep_for_internal(const detail::platform_duration& ts);
0313 }
0314
0315 #if defined BOOST_THREAD_USES_DATETIME
0316 #ifdef __DECXXX
0317
0318 template<>
0319 #endif
0320 inline void sleep(system_time const& abs_time)
0321 {
0322 const detail::real_platform_timepoint ts(abs_time);
0323 detail::platform_duration d(ts - detail::real_platform_clock::now());
0324 while (d > detail::platform_duration::zero())
0325 {
0326 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0327 hidden::sleep_for_internal(d);
0328 d = ts - detail::real_platform_clock::now();
0329 }
0330 }
0331
0332 template<typename TimeDuration>
0333 void sleep(TimeDuration const& rel_time)
0334 {
0335 hidden::sleep_for_internal(detail::platform_duration(rel_time));
0336 }
0337 #endif
0338
0339 #ifdef BOOST_THREAD_USES_CHRONO
0340 template <class Rep, class Period>
0341 void sleep_for(const chrono::duration<Rep, Period>& d)
0342 {
0343 hidden::sleep_for_internal(detail::platform_duration(d));
0344 }
0345
0346 template <class Duration>
0347 void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
0348 {
0349 sleep_for(t - chrono::steady_clock::now());
0350 }
0351
0352 template <class Clock, class Duration>
0353 void sleep_until(const chrono::time_point<Clock, Duration>& t)
0354 {
0355 typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
0356 common_duration d(t - Clock::now());
0357 while (d > common_duration::zero())
0358 {
0359 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
0360 hidden::sleep_for_internal(detail::platform_duration(d));
0361 d = t - Clock::now();
0362 }
0363 }
0364 #endif
0365
0366 #else
0367
0368
0369
0370 #if defined BOOST_THREAD_USES_DATETIME
0371 #ifdef __DECXXX
0372
0373 template<>
0374 #endif
0375 inline void sleep(system_time const& abs_time)
0376 {
0377 this_thread::sleep(abs_time);
0378 }
0379
0380 template<typename TimeDuration>
0381 void sleep(TimeDuration const& rel_time)
0382 {
0383 this_thread::sleep(rel_time);
0384 }
0385 #endif
0386
0387 #ifdef BOOST_THREAD_USES_CHRONO
0388 template <class Clock, class Duration>
0389 void sleep_until(const chrono::time_point<Clock, Duration>& t)
0390 {
0391 this_thread::sleep_until(t);
0392 }
0393
0394 template <class Rep, class Period>
0395 void sleep_for(const chrono::duration<Rep, Period>& d)
0396 {
0397 this_thread::sleep_for(d);
0398 }
0399 #endif
0400
0401 #endif
0402 }
0403 }
0404 }
0405
0406 #include <boost/config/abi_suffix.hpp>
0407
0408 #endif