LCOV - code coverage report
Current view: top level - usr/include/boost/thread/pthread - recursive_mutex.hpp (source / functions) Hit Total Coverage
Test: bitcoincash_test.info Lines: 23 28 82.1 %
Date: 2018-04-13 15:12:50 Functions: 5 5 100.0 %

          Line data    Source code
       1             : #ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
       2             : #define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
       3             : // (C) Copyright 2007-8 Anthony Williams
       4             : // (C) Copyright 2011-2012 Vicente J. Botet Escriba
       5             : // Distributed under the Boost Software License, Version 1.0. (See
       6             : // accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : 
       9             : #include <pthread.h>
      10             : #include <boost/throw_exception.hpp>
      11             : #include <boost/thread/exceptions.hpp>
      12             : #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
      13             : #include <boost/thread/lock_types.hpp>
      14             : #endif
      15             : #include <boost/thread/thread_time.hpp>
      16             : #include <boost/assert.hpp>
      17             : #ifndef _WIN32
      18             : #include <unistd.h>
      19             : #endif
      20             : #include <boost/date_time/posix_time/conversion.hpp>
      21             : #include <errno.h>
      22             : #include <boost/thread/pthread/timespec.hpp>
      23             : #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
      24             : #ifdef BOOST_THREAD_USES_CHRONO
      25             : #include <boost/chrono/system_clocks.hpp>
      26             : #include <boost/chrono/ceil.hpp>
      27             : #endif
      28             : #include <boost/thread/detail/delete.hpp>
      29             : 
      30             : #if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \
      31             :  || (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21)
      32             : #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
      33             : #define BOOST_PTHREAD_HAS_TIMEDLOCK
      34             : #endif
      35             : #endif
      36             : 
      37             : #if  defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
      38             :  ||  defined __ANDROID__
      39             : #define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
      40             : #endif
      41             : 
      42             : #if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
      43             : #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
      44             : #endif
      45             : 
      46             : #include <boost/config/abi_prefix.hpp>
      47             : 
      48             : namespace boost
      49             : {
      50             :     class recursive_mutex
      51             :     {
      52             :     private:
      53             :         pthread_mutex_t m;
      54             : #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
      55             :         pthread_cond_t cond;
      56             :         bool is_locked;
      57             :         pthread_t owner;
      58             :         unsigned count;
      59             : #endif
      60             :     public:
      61             :         BOOST_THREAD_NO_COPYABLE(recursive_mutex)
      62         474 :         recursive_mutex()
      63             :         {
      64             : #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
      65             :             pthread_mutexattr_t attr;
      66             : 
      67         474 :             int const init_attr_res=pthread_mutexattr_init(&attr);
      68         474 :             if(init_attr_res)
      69             :             {
      70           0 :                 boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init"));
      71             :             }
      72         474 :             int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
      73         474 :             if(set_attr_res)
      74             :             {
      75           0 :                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
      76           0 :                 boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype"));
      77             :             }
      78             : 
      79         474 :             int const res=pthread_mutex_init(&m,&attr);
      80         474 :             if(res)
      81             :             {
      82           0 :                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
      83           0 :                 boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
      84             :             }
      85         474 :             BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
      86             : #else
      87             :             int const res=pthread_mutex_init(&m,NULL);
      88             :             if(res)
      89             :             {
      90             :                 boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
      91             :             }
      92             :             int const res2=pthread_cond_init(&cond,NULL);
      93             :             if(res2)
      94             :             {
      95             :                 BOOST_VERIFY(!pthread_mutex_destroy(&m));
      96             :                 boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
      97             :             }
      98             :             is_locked=false;
      99             :             count=0;
     100             : #endif
     101         474 :         }
     102          42 :         ~recursive_mutex()
     103          42 :         {
     104          42 :             BOOST_VERIFY(!pthread_mutex_destroy(&m));
     105             : #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
     106             :             BOOST_VERIFY(!pthread_cond_destroy(&cond));
     107             : #endif
     108          42 :         }
     109             : 
     110             : #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
     111      226645 :         void lock()
     112             :         {
     113      226645 :             BOOST_VERIFY(!pthread_mutex_lock(&m));
     114      226645 :         }
     115             : 
     116      477226 :         void unlock()
     117             :         {
     118      477226 :             BOOST_VERIFY(!pthread_mutex_unlock(&m));
     119      477226 :         }
     120             : 
     121           8 :         bool try_lock() BOOST_NOEXCEPT
     122             :         {
     123           8 :             int const res=pthread_mutex_trylock(&m);
     124           8 :             BOOST_ASSERT(!res || res==EBUSY);
     125           8 :             return !res;
     126             :         }
     127             : #define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE
     128             :         typedef pthread_mutex_t* native_handle_type;
     129             :         native_handle_type native_handle()
     130             :         {
     131             :             return &m;
     132             :         }
     133             : 
     134             : #else
     135             :         void lock()
     136             :         {
     137             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     138             :             if(is_locked && pthread_equal(owner,pthread_self()))
     139             :             {
     140             :                 ++count;
     141             :                 return;
     142             :             }
     143             : 
     144             :             while(is_locked)
     145             :             {
     146             :                 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
     147             :             }
     148             :             is_locked=true;
     149             :             ++count;
     150             :             owner=pthread_self();
     151             :         }
     152             : 
     153             :         void unlock()
     154             :         {
     155             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     156             :             if(!--count)
     157             :             {
     158             :                 is_locked=false;
     159             :             }
     160             :             BOOST_VERIFY(!pthread_cond_signal(&cond));
     161             :         }
     162             : 
     163             :         bool try_lock()
     164             :         {
     165             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     166             :             if(is_locked && !pthread_equal(owner,pthread_self()))
     167             :             {
     168             :                 return false;
     169             :             }
     170             :             is_locked=true;
     171             :             ++count;
     172             :             owner=pthread_self();
     173             :             return true;
     174             :         }
     175             : 
     176             : #endif
     177             : 
     178             : #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
     179             :         typedef unique_lock<recursive_mutex> scoped_lock;
     180             :         typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
     181             : #endif
     182             :     };
     183             : 
     184             :     typedef recursive_mutex recursive_try_mutex;
     185             : 
     186             :     class recursive_timed_mutex
     187             :     {
     188             :     private:
     189             :         pthread_mutex_t m;
     190             : #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
     191             :         pthread_cond_t cond;
     192             :         bool is_locked;
     193             :         pthread_t owner;
     194             :         unsigned count;
     195             : #endif
     196             :     public:
     197             :         BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
     198             :         recursive_timed_mutex()
     199             :         {
     200             : #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
     201             :             pthread_mutexattr_t attr;
     202             : 
     203             :             int const init_attr_res=pthread_mutexattr_init(&attr);
     204             :             if(init_attr_res)
     205             :             {
     206             :                 boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init"));
     207             :             }
     208             :             int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
     209             :             if(set_attr_res)
     210             :             {
     211             :                 boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype"));
     212             :             }
     213             : 
     214             :             int const res=pthread_mutex_init(&m,&attr);
     215             :             if(res)
     216             :             {
     217             :                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
     218             :                 boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
     219             :             }
     220             :             BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
     221             : #else
     222             :             int const res=pthread_mutex_init(&m,NULL);
     223             :             if(res)
     224             :             {
     225             :                 boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
     226             :             }
     227             :             int const res2=pthread_cond_init(&cond,NULL);
     228             :             if(res2)
     229             :             {
     230             :                 BOOST_VERIFY(!pthread_mutex_destroy(&m));
     231             :                 boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
     232             :             }
     233             :             is_locked=false;
     234             :             count=0;
     235             : #endif
     236             :         }
     237             :         ~recursive_timed_mutex()
     238             :         {
     239             :             BOOST_VERIFY(!pthread_mutex_destroy(&m));
     240             : #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
     241             :             BOOST_VERIFY(!pthread_cond_destroy(&cond));
     242             : #endif
     243             :         }
     244             : 
     245             : #if defined BOOST_THREAD_USES_DATETIME
     246             :         template<typename TimeDuration>
     247             :         bool timed_lock(TimeDuration const & relative_time)
     248             :         {
     249             :             return timed_lock(get_system_time()+relative_time);
     250             :         }
     251             : #endif
     252             : 
     253             : #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
     254             :         void lock()
     255             :         {
     256             :             BOOST_VERIFY(!pthread_mutex_lock(&m));
     257             :         }
     258             : 
     259             :         void unlock()
     260             :         {
     261             :             BOOST_VERIFY(!pthread_mutex_unlock(&m));
     262             :         }
     263             : 
     264             :         bool try_lock()
     265             :         {
     266             :             int const res=pthread_mutex_trylock(&m);
     267             :             BOOST_ASSERT(!res || res==EBUSY);
     268             :             return !res;
     269             :         }
     270             :     private:
     271             :         bool do_try_lock_until(struct timespec const &timeout)
     272             :         {
     273             :             int const res=pthread_mutex_timedlock(&m,&timeout);
     274             :             BOOST_ASSERT(!res || res==ETIMEDOUT);
     275             :             return !res;
     276             :         }
     277             : 
     278             :     public:
     279             : 
     280             : #else
     281             :         void lock()
     282             :         {
     283             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     284             :             if(is_locked && pthread_equal(owner,pthread_self()))
     285             :             {
     286             :                 ++count;
     287             :                 return;
     288             :             }
     289             : 
     290             :             while(is_locked)
     291             :             {
     292             :                 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
     293             :             }
     294             :             is_locked=true;
     295             :             ++count;
     296             :             owner=pthread_self();
     297             :         }
     298             : 
     299             :         void unlock()
     300             :         {
     301             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     302             :             if(!--count)
     303             :             {
     304             :                 is_locked=false;
     305             :             }
     306             :             BOOST_VERIFY(!pthread_cond_signal(&cond));
     307             :         }
     308             : 
     309             :         bool try_lock() BOOST_NOEXCEPT
     310             :         {
     311             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     312             :             if(is_locked && !pthread_equal(owner,pthread_self()))
     313             :             {
     314             :                 return false;
     315             :             }
     316             :             is_locked=true;
     317             :             ++count;
     318             :             owner=pthread_self();
     319             :             return true;
     320             :         }
     321             : 
     322             :     private:
     323             :         bool do_try_lock_until(struct timespec const &timeout)
     324             :         {
     325             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     326             :             if(is_locked && pthread_equal(owner,pthread_self()))
     327             :             {
     328             :                 ++count;
     329             :                 return true;
     330             :             }
     331             :             while(is_locked)
     332             :             {
     333             :                 int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
     334             :                 if(cond_res==ETIMEDOUT)
     335             :                 {
     336             :                     return false;
     337             :                 }
     338             :                 BOOST_ASSERT(!cond_res);
     339             :             }
     340             :             is_locked=true;
     341             :             ++count;
     342             :             owner=pthread_self();
     343             :             return true;
     344             :         }
     345             :     public:
     346             : 
     347             : #endif
     348             : 
     349             : #if defined BOOST_THREAD_USES_DATETIME
     350             :         bool timed_lock(system_time const & abs_time)
     351             :         {
     352             :             struct timespec const ts=detail::to_timespec(abs_time);
     353             :             return do_try_lock_until(ts);
     354             :         }
     355             : #endif
     356             : #ifdef BOOST_THREAD_USES_CHRONO
     357             :         template <class Rep, class Period>
     358             :         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
     359             :         {
     360             :           return try_lock_until(chrono::steady_clock::now() + rel_time);
     361             :         }
     362             :         template <class Clock, class Duration>
     363             :         bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
     364             :         {
     365             :           using namespace chrono;
     366             :           system_clock::time_point     s_now = system_clock::now();
     367             :           typename Clock::time_point  c_now = Clock::now();
     368             :           return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
     369             :         }
     370             :         template <class Duration>
     371             :         bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
     372             :         {
     373             :           using namespace chrono;
     374             :           typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
     375             :           return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
     376             :         }
     377             :         bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
     378             :         {
     379             :           //using namespace chrono;
     380             :           chrono::nanoseconds d = tp.time_since_epoch();
     381             :           timespec ts = boost::detail::to_timespec(d);
     382             :           return do_try_lock_until(ts);
     383             :         }
     384             : #endif
     385             : 
     386             : #define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE
     387             :         typedef pthread_mutex_t* native_handle_type;
     388             :         native_handle_type native_handle()
     389             :         {
     390             :             return &m;
     391             :         }
     392             : 
     393             : #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
     394             :         typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
     395             :         typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
     396             :         typedef scoped_timed_lock scoped_lock;
     397             : #endif
     398             :     };
     399             : 
     400             : }
     401             : 
     402             : #include <boost/config/abi_suffix.hpp>
     403             : 
     404             : #endif

Generated by: LCOV version 1.12