Back to home page

EIC code displayed by LXR

 
 

    


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 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 // (C) Copyright 2007 Anthony Williams
0007 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
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         // stack
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 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0126             // These data must be at the end so that the access to the other fields doesn't change
0127             // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
0128             // Another option is to have them always
0129             pthread_mutex_t* cond_mutex;
0130             pthread_cond_t* current_cond;
0131 //#endif
0132             typedef std::vector<std::pair<condition_variable*, mutex*>
0133             //, hidden_allocator<std::pair<condition_variable*, mutex*> >
0134             > notify_list_t;
0135             notify_list_t notify;
0136 
0137 //#ifndef BOOST_NO_EXCEPTIONS
0138             typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
0139             async_states_t async_states_;
0140 //#endif
0141 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0142             // These data must be at the end so that the access to the other fields doesn't change
0143             // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
0144             // Another option is to have them always
0145             bool interrupt_enabled;
0146             bool interrupt_requested;
0147 //#endif
0148             thread_data_base():
0149                 thread_handle(0),
0150                 done(false),join_started(false),joined(false),
0151                 thread_exit_callbacks(0),
0152 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0153                 cond_mutex(0),
0154                 current_cond(0),
0155 //#endif
0156                 notify()
0157 //#ifndef BOOST_NO_EXCEPTIONS
0158                 , async_states_()
0159 //#endif
0160 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0161                 , interrupt_enabled(true)
0162                 , interrupt_requested(false)
0163 //#endif
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 //#ifndef BOOST_NO_EXCEPTIONS
0176             void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
0177             {
0178               async_states_.push_back(as);
0179             }
0180 //#endif
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(); // BOOST_NO_EXCEPTIONS protected
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         /// Workaround of DECCXX issue of incorrect template substitution
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 // Use pthread_delay_np or nanosleep when available
0308 // because they do not provide an interruption point.
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           /// Workaround of DECCXX issue of incorrect template substitution
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 // BOOST_THREAD_SLEEP_FOR_IS_STEADY
0367 // When pthread_delay_np and nanosleep are not available,
0368 // fall back to using the interruptible sleep functions.
0369 
0370 #if defined BOOST_THREAD_USES_DATETIME
0371 #ifdef __DECXXX
0372           /// Workaround of DECCXX issue of incorrect template substitution
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 // BOOST_THREAD_SLEEP_FOR_IS_STEADY
0402         } // no_interruption_point
0403     } // this_thread
0404 }
0405 
0406 #include <boost/config/abi_suffix.hpp>
0407 
0408 #endif