LCOV - code coverage report
Current view: top level - usr/include/boost/thread/pthread - condition_variable.hpp (source / functions) Hit Total Coverage
Test: bitcoincash_test.info Lines: 8 27 29.6 %
Date: 2018-04-13 15:12:50 Functions: 2 4 50.0 %

          Line data    Source code
       1             : #ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
       2             : #define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_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-10 Anthony Williams
       7             : // (C) Copyright 2011-2012 Vicente J. Botet Escriba
       8             : 
       9             : #include <boost/thread/pthread/timespec.hpp>
      10             : #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
      11             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
      12             : #include <boost/thread/pthread/thread_data.hpp>
      13             : #endif
      14             : #include <boost/thread/pthread/condition_variable_fwd.hpp>
      15             : #ifdef BOOST_THREAD_USES_CHRONO
      16             : #include <boost/chrono/system_clocks.hpp>
      17             : #include <boost/chrono/ceil.hpp>
      18             : #endif
      19             : #include <boost/thread/detail/delete.hpp>
      20             : 
      21             : #include <boost/config/abi_prefix.hpp>
      22             : 
      23             : namespace boost
      24             : {
      25             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
      26             :     namespace this_thread
      27             :     {
      28             :         void BOOST_THREAD_DECL interruption_point();
      29             :     }
      30             : #endif
      31             : 
      32             :     namespace thread_cv_detail
      33             :     {
      34             :         template<typename MutexType>
      35             :         struct lock_on_exit
      36             :         {
      37             :             MutexType* m;
      38             : 
      39             :             lock_on_exit():
      40           0 :                 m(0)
      41             :             {}
      42             : 
      43             :             void activate(MutexType& m_)
      44             :             {
      45           0 :                 m_.unlock();
      46             :                 m=&m_;
      47             :             }
      48             :             ~lock_on_exit()
      49             :             {
      50           0 :                 if(m)
      51             :                 {
      52           0 :                     m->lock();
      53             :                 }
      54           0 :            }
      55             :         };
      56             :     }
      57             : 
      58           0 :     inline void condition_variable::wait(unique_lock<mutex>& m)
      59             :     {
      60             : #if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
      61             :         if(! m.owns_lock())
      62             :         {
      63             :             boost::throw_exception(condition_error(-1, "boost::condition_variable::wait() failed precondition mutex not owned"));
      64             :         }
      65             : #endif
      66           0 :         int res=0;
      67             :         {
      68             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
      69           0 :             thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
      70           0 :             detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
      71             :             guard.activate(m);
      72             :             do {
      73           0 :               res = pthread_cond_wait(&cond,&internal_mutex);
      74           0 :             } while (res == EINTR);
      75             : #else
      76             :             //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
      77             :             pthread_mutex_t* the_mutex = m.mutex()->native_handle();
      78             :             do {
      79             :               res = pthread_cond_wait(&cond,the_mutex);
      80             :             } while (res == EINTR);
      81             : #endif
      82             :         }
      83             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
      84           0 :         this_thread::interruption_point();
      85             : #endif
      86           0 :         if(res)
      87             :         {
      88           0 :             boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait"));
      89             :         }
      90           0 :     }
      91             : 
      92             :     inline bool condition_variable::do_wait_until(
      93             :                 unique_lock<mutex>& m,
      94             :                 struct timespec const &timeout)
      95             :     {
      96             : #if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
      97             :         if (!m.owns_lock())
      98             :         {
      99             :             boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned"));
     100             :         }
     101             : #endif
     102             :         thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
     103             :         int cond_res;
     104             :         {
     105             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     106             :             detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
     107             :             guard.activate(m);
     108             :             cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
     109             : #else
     110             :             //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
     111             :             pthread_mutex_t* the_mutex = m.mutex()->native_handle();
     112             :             cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
     113             : #endif
     114             :         }
     115             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     116             :         this_thread::interruption_point();
     117             : #endif
     118             :         if(cond_res==ETIMEDOUT)
     119             :         {
     120             :             return false;
     121             :         }
     122             :         if(cond_res)
     123             :         {
     124             :             boost::throw_exception(condition_error(cond_res, "boost::condition_variable::do_wait_until failed in pthread_cond_timedwait"));
     125             :         }
     126             :         return true;
     127             :     }
     128             : 
     129       23264 :     inline void condition_variable::notify_one() BOOST_NOEXCEPT
     130             :     {
     131             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     132       46528 :         boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
     133             : #endif
     134       23264 :         BOOST_VERIFY(!pthread_cond_signal(&cond));
     135       23264 :     }
     136             : 
     137       23072 :     inline void condition_variable::notify_all() BOOST_NOEXCEPT
     138             :     {
     139             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     140       46144 :         boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
     141             : #endif
     142       23072 :         BOOST_VERIFY(!pthread_cond_broadcast(&cond));
     143       23072 :     }
     144             : 
     145             :     class condition_variable_any
     146             :     {
     147             :         pthread_mutex_t internal_mutex;
     148             :         pthread_cond_t cond;
     149             : 
     150             :     public:
     151             :         BOOST_THREAD_NO_COPYABLE(condition_variable_any)
     152             :         condition_variable_any()
     153             :         {
     154             :             int const res=pthread_mutex_init(&internal_mutex,NULL);
     155             :             if(res)
     156             :             {
     157             :                 boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
     158             :             }
     159             :             int const res2=pthread_cond_init(&cond,NULL);
     160             :             if(res2)
     161             :             {
     162             :                 BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
     163             :                 boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init"));
     164             :             }
     165             :         }
     166             :         ~condition_variable_any()
     167             :         {
     168             :             BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
     169             :             BOOST_VERIFY(!pthread_cond_destroy(&cond));
     170             :         }
     171             : 
     172             :         template<typename lock_type>
     173             :         void wait(lock_type& m)
     174             :         {
     175             :             int res=0;
     176             :             {
     177             :                 thread_cv_detail::lock_on_exit<lock_type> guard;
     178             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     179             :                 detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
     180             : #else
     181             :             boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
     182             : #endif
     183             :                 guard.activate(m);
     184             :                 res=pthread_cond_wait(&cond,&internal_mutex);
     185             :             }
     186             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     187             :             this_thread::interruption_point();
     188             : #endif
     189             :             if(res)
     190             :             {
     191             :                 boost::throw_exception(condition_error(res, "boost::condition_variable_any::wait() failed in pthread_cond_wait"));
     192             :             }
     193             :         }
     194             : 
     195             :         template<typename lock_type,typename predicate_type>
     196             :         void wait(lock_type& m,predicate_type pred)
     197             :         {
     198             :             while(!pred()) wait(m);
     199             :         }
     200             : 
     201             : #if defined BOOST_THREAD_USES_DATETIME
     202             :         template<typename lock_type>
     203             :         bool timed_wait(lock_type& m,boost::system_time const& abs_time)
     204             :         {
     205             :             struct timespec const timeout=detail::to_timespec(abs_time);
     206             :             return do_wait_until(m, timeout);
     207             :         }
     208             :         template<typename lock_type>
     209             :         bool timed_wait(lock_type& m,xtime const& abs_time)
     210             :         {
     211             :             return timed_wait(m,system_time(abs_time));
     212             :         }
     213             : 
     214             :         template<typename lock_type,typename duration_type>
     215             :         bool timed_wait(lock_type& m,duration_type const& wait_duration)
     216             :         {
     217             :             return timed_wait(m,get_system_time()+wait_duration);
     218             :         }
     219             : 
     220             :         template<typename lock_type,typename predicate_type>
     221             :         bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
     222             :         {
     223             :             while (!pred())
     224             :             {
     225             :                 if(!timed_wait(m, abs_time))
     226             :                     return pred();
     227             :             }
     228             :             return true;
     229             :         }
     230             : 
     231             :         template<typename lock_type,typename predicate_type>
     232             :         bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred)
     233             :         {
     234             :             return timed_wait(m,system_time(abs_time),pred);
     235             :         }
     236             : 
     237             :         template<typename lock_type,typename duration_type,typename predicate_type>
     238             :         bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
     239             :         {
     240             :             return timed_wait(m,get_system_time()+wait_duration,pred);
     241             :         }
     242             : #endif
     243             : #ifdef BOOST_THREAD_USES_CHRONO
     244             :         template <class lock_type,class Duration>
     245             :         cv_status
     246             :         wait_until(
     247             :                 lock_type& lock,
     248             :                 const chrono::time_point<chrono::system_clock, Duration>& t)
     249             :         {
     250             :           using namespace chrono;
     251             :           typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
     252             :           wait_until(lock,
     253             :                         nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
     254             :           return system_clock::now() < t ? cv_status::no_timeout :
     255             :                                              cv_status::timeout;
     256             :         }
     257             : 
     258             :         template <class lock_type, class Clock, class Duration>
     259             :         cv_status
     260             :         wait_until(
     261             :                 lock_type& lock,
     262             :                 const chrono::time_point<Clock, Duration>& t)
     263             :         {
     264             :           using namespace chrono;
     265             :           system_clock::time_point     s_now = system_clock::now();
     266             :           typename Clock::time_point  c_now = Clock::now();
     267             :           wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
     268             :           return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
     269             :         }
     270             : 
     271             :         template <class lock_type, class Clock, class Duration, class Predicate>
     272             :         bool
     273             :         wait_until(
     274             :                 lock_type& lock,
     275             :                 const chrono::time_point<Clock, Duration>& t,
     276             :                 Predicate pred)
     277             :         {
     278             :             while (!pred())
     279             :             {
     280             :                 if (wait_until(lock, t) == cv_status::timeout)
     281             :                     return pred();
     282             :             }
     283             :             return true;
     284             :         }
     285             : 
     286             : 
     287             :         template <class lock_type, class Rep, class Period>
     288             :         cv_status
     289             :         wait_for(
     290             :                 lock_type& lock,
     291             :                 const chrono::duration<Rep, Period>& d)
     292             :         {
     293             :           using namespace chrono;
     294             :           system_clock::time_point s_now = system_clock::now();
     295             :           steady_clock::time_point c_now = steady_clock::now();
     296             :           wait_until(lock, s_now + ceil<nanoseconds>(d));
     297             :           return steady_clock::now() - c_now < d ? cv_status::no_timeout :
     298             :                                                    cv_status::timeout;
     299             : 
     300             :         }
     301             : 
     302             : 
     303             :         template <class lock_type, class Rep, class Period, class Predicate>
     304             :         bool
     305             :         wait_for(
     306             :                 lock_type& lock,
     307             :                 const chrono::duration<Rep, Period>& d,
     308             :                 Predicate pred)
     309             :         {
     310             :           return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
     311             : 
     312             : //          while (!pred())
     313             : //          {
     314             : //              if (wait_for(lock, d) == cv_status::timeout)
     315             : //                  return pred();
     316             : //          }
     317             : //          return true;
     318             :         }
     319             : 
     320             :         template <class lock_type>
     321             :         cv_status wait_until(
     322             :             lock_type& lk,
     323             :             chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
     324             :         {
     325             :             using namespace chrono;
     326             :             nanoseconds d = tp.time_since_epoch();
     327             :             timespec ts = boost::detail::to_timespec(d);
     328             :             if (do_wait_until(lk, ts)) return cv_status::no_timeout;
     329             :             else return cv_status::timeout;
     330             :         }
     331             : #endif
     332             : 
     333             :         void notify_one() BOOST_NOEXCEPT
     334             :         {
     335             :             boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
     336             :             BOOST_VERIFY(!pthread_cond_signal(&cond));
     337             :         }
     338             : 
     339           0 :         void notify_all() BOOST_NOEXCEPT
     340             :         {
     341           0 :             boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
     342           0 :             BOOST_VERIFY(!pthread_cond_broadcast(&cond));
     343           0 :         }
     344             :     private: // used by boost::thread::try_join_until
     345             : 
     346             :         template <class lock_type>
     347             :         inline bool do_wait_until(
     348             :           lock_type& m,
     349             :           struct timespec const &timeout)
     350             :         {
     351             :           int res=0;
     352             :           {
     353             :               thread_cv_detail::lock_on_exit<lock_type> guard;
     354             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     355             :               detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
     356             : #else
     357             :             boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
     358             : #endif
     359             :               guard.activate(m);
     360             :               res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
     361             :           }
     362             : #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     363             :           this_thread::interruption_point();
     364             : #endif
     365             :           if(res==ETIMEDOUT)
     366             :           {
     367             :               return false;
     368             :           }
     369             :           if(res)
     370             :           {
     371             :               boost::throw_exception(condition_error(res, "boost::condition_variable_any::do_wait_until() failed in pthread_cond_timedwait"));
     372             :           }
     373             :           return true;
     374             :         }
     375             : 
     376             : 
     377             :     };
     378             : 
     379             : }
     380             : 
     381             : #include <boost/config/abi_suffix.hpp>
     382             : 
     383             : #endif

Generated by: LCOV version 1.12