LCOV - code coverage report
Current view: top level - usr/include/boost/thread/pthread - thread_data.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 27 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 2007 Anthony Williams
       7             : // (C) Copyright 2011-2012 Vicente J. Botet Escriba
       8             : 
       9             : #include <boost/thread/detail/config.hpp>
      10             : #include <boost/thread/exceptions.hpp>
      11             : #include <boost/thread/lock_guard.hpp>
      12             : #include <boost/thread/lock_types.hpp>
      13             : #include <boost/thread/mutex.hpp>
      14             : #include <boost/thread/pthread/condition_variable_fwd.hpp>
      15             : #include <boost/thread/pthread/pthread_helpers.hpp>
      16             : 
      17             : #include <boost/shared_ptr.hpp>
      18             : #include <boost/enable_shared_from_this.hpp>
      19             : #include <boost/assert.hpp>
      20             : #include <boost/thread/detail/platform_time.hpp>
      21             : #ifdef BOOST_THREAD_USES_CHRONO
      22             : #include <boost/chrono/system_clocks.hpp>
      23             : #endif
      24             : 
      25             : #include <map>
      26             : #include <vector>
      27             : #include <utility>
      28             : 
      29             : #if defined(__ANDROID__)
      30             : # ifndef PAGE_SIZE
      31             : #  define PAGE_SIZE 4096
      32             : # endif
      33             : #endif
      34             : 
      35             : #include <pthread.h>
      36             : #include <unistd.h>
      37             : 
      38             : #include <boost/config/abi_prefix.hpp>
      39             : 
      40             : namespace boost
      41             : {
      42             :     class thread_attributes {
      43             :     public:
      44             :         thread_attributes() BOOST_NOEXCEPT {
      45             :             int res = pthread_attr_init(&val_);
      46             :             BOOST_VERIFY(!res && "pthread_attr_init failed");
      47             :         }
      48             :         ~thread_attributes() {
      49             :           int res = pthread_attr_destroy(&val_);
      50             :           BOOST_VERIFY(!res && "pthread_attr_destroy failed");
      51             :         }
      52             :         // stack
      53             :         void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
      54             :           if (size==0) return;
      55             : #ifdef BOOST_THREAD_USES_GETPAGESIZE
      56             :           std::size_t page_size = getpagesize();
      57             : #else
      58             :           std::size_t page_size = ::sysconf( _SC_PAGESIZE);
      59             : #endif
      60             : #if PTHREAD_STACK_MIN > 0
      61             :           if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
      62             : #endif
      63             :           size = ((size+page_size-1)/page_size)*page_size;
      64             :           int res = pthread_attr_setstacksize(&val_, size);
      65             :           BOOST_VERIFY(!res && "pthread_attr_setstacksize failed");
      66             :         }
      67             : 
      68             :         std::size_t get_stack_size() const BOOST_NOEXCEPT {
      69             :             std::size_t size;
      70             :             int res = pthread_attr_getstacksize(&val_, &size);
      71             :             BOOST_VERIFY(!res && "pthread_attr_getstacksize failed");
      72             :             return size;
      73             :         }
      74             : #define BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE
      75             : 
      76             :         typedef pthread_attr_t native_handle_type;
      77             :         native_handle_type* native_handle() BOOST_NOEXCEPT {
      78             :           return &val_;
      79             :         }
      80             :         const native_handle_type* native_handle() const BOOST_NOEXCEPT {
      81             :           return &val_;
      82             :         }
      83             : 
      84             :     private:
      85             :         pthread_attr_t val_;
      86             :     };
      87             : 
      88             :     class thread;
      89             : 
      90             :     namespace detail
      91             :     {
      92             :         struct shared_state_base;
      93             :         struct tss_cleanup_function;
      94             :         struct thread_exit_callback_node;
      95             :         struct tss_data_node
      96             :         {
      97             :             typedef void(*cleanup_func_t)(void*);
      98             :             typedef void(*cleanup_caller_t)(cleanup_func_t, void*);
      99             : 
     100             :             cleanup_caller_t caller;
     101             :             cleanup_func_t func;
     102             :             void* value;
     103             : 
     104             :             tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_):
     105             :                 caller(caller_),func(func_),value(value_)
     106             :             {}
     107             :         };
     108             : 
     109             :         struct thread_data_base;
     110             :         typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
     111             : 
     112             :         struct BOOST_THREAD_DECL thread_data_base:
     113             :             enable_shared_from_this<thread_data_base>
     114             :         {
     115             :             thread_data_ptr self;
     116             :             pthread_t thread_handle;
     117             :             boost::mutex data_mutex;
     118             :             boost::condition_variable done_condition;
     119             :             bool done;
     120             :             bool join_started;
     121             :             bool joined;
     122             :             boost::detail::thread_exit_callback_node* thread_exit_callbacks;
     123             :             std::map<void const*,boost::detail::tss_data_node> tss_data;
     124             : 
     125             : //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     126             :             // These data must be at the end so that the access to the other fields doesn't change
     127             :             // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
     128             :             // Another option is to have them always
     129             :             pthread_mutex_t* cond_mutex;
     130             :             pthread_cond_t* current_cond;
     131             : //#endif
     132             :             typedef std::vector<std::pair<condition_variable*, mutex*>
     133             :             //, hidden_allocator<std::pair<condition_variable*, mutex*> >
     134             :             > notify_list_t;
     135             :             notify_list_t notify;
     136             : 
     137             : //#ifndef BOOST_NO_EXCEPTIONS
     138             :             typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
     139             :             async_states_t async_states_;
     140             : //#endif
     141             : //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     142             :             // These data must be at the end so that the access to the other fields doesn't change
     143             :             // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
     144             :             // Another option is to have them always
     145             :             bool interrupt_enabled;
     146             :             bool interrupt_requested;
     147             : //#endif
     148             :             thread_data_base():
     149             :                 thread_handle(0),
     150             :                 done(false),join_started(false),joined(false),
     151             :                 thread_exit_callbacks(0),
     152             : //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     153             :                 cond_mutex(0),
     154             :                 current_cond(0),
     155             : //#endif
     156             :                 notify()
     157             : //#ifndef BOOST_NO_EXCEPTIONS
     158             :                 , async_states_()
     159             : //#endif
     160             : //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     161             :                 , interrupt_enabled(true)
     162             :                 , interrupt_requested(false)
     163             : //#endif
     164             :             {}
     165             :             virtual ~thread_data_base();
     166             : 
     167             :             typedef pthread_t native_handle_type;
     168             : 
     169             :             virtual void run()=0;
     170           0 :             virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
     171             :             {
     172           0 :               notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
     173           0 :             }
     174             : 
     175             : //#ifndef BOOST_NO_EXCEPTIONS
     176             :             void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
     177             :             {
     178             :               async_states_.push_back(as);
     179             :             }
     180             : //#endif
     181             :         };
     182             : 
     183             :         BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
     184             : 
     185             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     186             :         class interruption_checker
     187             :         {
     188             :             thread_data_base* const thread_info;
     189             :             pthread_mutex_t* m;
     190             :             bool set;
     191             :             bool done;
     192             : 
     193             :             void check_for_interruption()
     194             :             {
     195             : #ifndef BOOST_NO_EXCEPTIONS
     196             :                 if(thread_info->interrupt_requested)
     197             :                 {
     198             :                     thread_info->interrupt_requested=false;
     199             :                     throw thread_interrupted(); // BOOST_NO_EXCEPTIONS protected
     200             :                 }
     201             : #endif
     202             :             }
     203             : 
     204             :             void operator=(interruption_checker&);
     205             :         public:
     206           0 :             explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
     207           0 :                 thread_info(detail::get_current_thread_data()),m(cond_mutex),
     208           0 :                 set(thread_info && thread_info->interrupt_enabled), done(false)
     209             :             {
     210           0 :                 if(set)
     211             :                 {
     212           0 :                     lock_guard<mutex> guard(thread_info->data_mutex);
     213           0 :                     check_for_interruption();
     214           0 :                     thread_info->cond_mutex=cond_mutex;
     215           0 :                     thread_info->current_cond=cond;
     216           0 :                     BOOST_VERIFY(!posix::pthread_mutex_lock(m));
     217             :                 }
     218             :                 else
     219             :                 {
     220           0 :                     BOOST_VERIFY(!posix::pthread_mutex_lock(m));
     221             :                 }
     222           0 :             }
     223           0 :             void unlock_if_locked()
     224             :             {
     225           0 :               if ( ! done) {
     226           0 :                 if (set)
     227             :                 {
     228           0 :                     BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
     229           0 :                     lock_guard<mutex> guard(thread_info->data_mutex);
     230           0 :                     thread_info->cond_mutex=NULL;
     231           0 :                     thread_info->current_cond=NULL;
     232             :                 }
     233             :                 else
     234             :                 {
     235           0 :                     BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
     236             :                 }
     237           0 :                 done = true;
     238             :               }
     239           0 :             }
     240             : 
     241           0 :             ~interruption_checker() BOOST_NOEXCEPT_IF(false)
     242           0 :             {
     243           0 :                 unlock_if_locked();
     244             :             }
     245             :         };
     246             : #endif
     247             :     }
     248             : 
     249             :     namespace this_thread
     250             :     {
     251             :         void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
     252             : 
     253             :         namespace hidden
     254             :         {
     255             :           inline bool always_false()
     256             :           {
     257             :             return false;
     258             :           }
     259             :         }
     260             : 
     261             : #if defined BOOST_THREAD_USES_DATETIME
     262             : #ifdef __DECXXX
     263             :         /// Workaround of DECCXX issue of incorrect template substitution
     264             :         template<>
     265             : #endif
     266             :         inline void sleep(system_time const& abs_time)
     267             :         {
     268             :           mutex mx;
     269             :           unique_lock<mutex> lock(mx);
     270             :           condition_variable cond;
     271             :           cond.timed_wait(lock, abs_time, hidden::always_false);
     272             :         }
     273             : 
     274             :         template<typename TimeDuration>
     275             :         void sleep(TimeDuration const& rel_time)
     276             :         {
     277             :           mutex mx;
     278             :           unique_lock<mutex> lock(mx);
     279             :           condition_variable cond;
     280             :           cond.timed_wait(lock, rel_time, hidden::always_false);
     281             :         }
     282             : #endif
     283             : 
     284             : #ifdef BOOST_THREAD_USES_CHRONO
     285             :         template <class Clock, class Duration>
     286             :         void sleep_until(const chrono::time_point<Clock, Duration>& t)
     287             :         {
     288             :           mutex mut;
     289             :           unique_lock<mutex> lk(mut);
     290             :           condition_variable cv;
     291             :           cv.wait_until(lk, t, hidden::always_false);
     292             :         }
     293             : 
     294             :         template <class Rep, class Period>
     295             :         void sleep_for(const chrono::duration<Rep, Period>& d)
     296             :         {
     297             :           mutex mut;
     298             :           unique_lock<mutex> lk(mut);
     299             :           condition_variable cv;
     300             :           cv.wait_for(lk, d, hidden::always_false);
     301             :         }
     302             : #endif
     303             : 
     304             :         namespace no_interruption_point
     305             :         {
     306             : #if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY
     307             : // Use pthread_delay_np or nanosleep when available
     308             : // because they do not provide an interruption point.
     309             : 
     310             :           namespace hidden
     311             :           {
     312             :             void BOOST_THREAD_DECL sleep_for_internal(const detail::platform_duration& ts);
     313             :           }
     314             : 
     315             : #if defined BOOST_THREAD_USES_DATETIME
     316             : #ifdef __DECXXX
     317             :           /// Workaround of DECCXX issue of incorrect template substitution
     318             :           template<>
     319             : #endif
     320             :           inline void sleep(system_time const& abs_time)
     321             :           {
     322             :             const detail::real_platform_timepoint ts(abs_time);
     323             :             detail::platform_duration d(ts - detail::real_platform_clock::now());
     324             :             while (d > detail::platform_duration::zero())
     325             :             {
     326             :               d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
     327             :               hidden::sleep_for_internal(d);
     328             :               d = ts - detail::real_platform_clock::now();
     329             :             }
     330             :           }
     331             : 
     332             :           template<typename TimeDuration>
     333             :           void sleep(TimeDuration const& rel_time)
     334             :           {
     335             :             hidden::sleep_for_internal(detail::platform_duration(rel_time));
     336             :           }
     337             : #endif
     338             : 
     339             : #ifdef BOOST_THREAD_USES_CHRONO
     340             :           template <class Rep, class Period>
     341             :           void sleep_for(const chrono::duration<Rep, Period>& d)
     342             :           {
     343             :             hidden::sleep_for_internal(detail::platform_duration(d));
     344             :           }
     345             : 
     346             :           template <class Duration>
     347             :           void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
     348             :           {
     349             :             sleep_for(t - chrono::steady_clock::now());
     350             :           }
     351             : 
     352             :           template <class Clock, class Duration>
     353             :           void sleep_until(const chrono::time_point<Clock, Duration>& t)
     354             :           {
     355             :             typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
     356             :             common_duration d(t - Clock::now());
     357             :             while (d > common_duration::zero())
     358             :             {
     359             :               d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
     360             :               hidden::sleep_for_internal(detail::platform_duration(d));
     361             :               d = t - Clock::now();
     362             :             }
     363             :           }
     364             : #endif
     365             : 
     366             : #else // BOOST_THREAD_SLEEP_FOR_IS_STEADY
     367             : // When pthread_delay_np and nanosleep are not available,
     368             : // fall back to using the interruptible sleep functions.
     369             : 
     370             : #if defined BOOST_THREAD_USES_DATETIME
     371             : #ifdef __DECXXX
     372             :           /// Workaround of DECCXX issue of incorrect template substitution
     373             :           template<>
     374             : #endif
     375             :           inline void sleep(system_time const& abs_time)
     376             :           {
     377             :             this_thread::sleep(abs_time);
     378             :           }
     379             : 
     380             :           template<typename TimeDuration>
     381             :           void sleep(TimeDuration const& rel_time)
     382             :           {
     383             :             this_thread::sleep(rel_time);
     384             :           }
     385             : #endif
     386             : 
     387             : #ifdef BOOST_THREAD_USES_CHRONO
     388             :           template <class Clock, class Duration>
     389             :           void sleep_until(const chrono::time_point<Clock, Duration>& t)
     390             :           {
     391             :             this_thread::sleep_until(t);
     392             :           }
     393             : 
     394             :           template <class Rep, class Period>
     395             :           void sleep_for(const chrono::duration<Rep, Period>& d)
     396             :           {
     397             :             this_thread::sleep_for(d);
     398             :           }
     399             : #endif
     400             : 
     401             : #endif // BOOST_THREAD_SLEEP_FOR_IS_STEADY
     402             :         } // no_interruption_point
     403             :     } // this_thread
     404             : }
     405             : 
     406             : #include <boost/config/abi_suffix.hpp>
     407             : 
     408             : #endif

Generated by: LCOV version 1.14