LCOV - code coverage report
Current view: top level - usr/include/boost/thread/pthread - mutex.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 16 22 72.7 %
Date: 2022-12-08 13:48:47 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
       2             : #define BOOST_THREAD_PTHREAD_MUTEX_HPP
       3             : // (C) Copyright 2007-8 Anthony Williams
       4             : // (C) Copyright 2011,2012,2015 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 <boost/thread/detail/config.hpp>
      10             : #include <boost/assert.hpp>
      11             : #include <pthread.h>
      12             : #include <boost/throw_exception.hpp>
      13             : #include <boost/core/ignore_unused.hpp>
      14             : #include <boost/thread/exceptions.hpp>
      15             : #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
      16             : #include <boost/thread/lock_types.hpp>
      17             : #endif
      18             : #include <boost/thread/thread_time.hpp>
      19             : #if defined BOOST_THREAD_USES_DATETIME
      20             : #include <boost/thread/xtime.hpp>
      21             : #endif
      22             : #include <boost/assert.hpp>
      23             : #include <errno.h>
      24             : #include <boost/thread/detail/platform_time.hpp>
      25             : #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
      26             : #include <boost/thread/pthread/pthread_helpers.hpp>
      27             : #ifdef BOOST_THREAD_USES_CHRONO
      28             : #include <boost/chrono/system_clocks.hpp>
      29             : #include <boost/chrono/ceil.hpp>
      30             : #endif
      31             : #include <boost/thread/detail/delete.hpp>
      32             : 
      33             : 
      34             : #include <boost/config/abi_prefix.hpp>
      35             : 
      36             : namespace boost
      37             : {
      38             : 
      39             :     class BOOST_THREAD_CAPABILITY("mutex") mutex
      40             :     {
      41             :     private:
      42             :         pthread_mutex_t m;
      43             :     public:
      44             :         BOOST_THREAD_NO_COPYABLE(mutex)
      45             : 
      46      428531 :         mutex()
      47      428531 :         {
      48      428531 :             int const res=posix::pthread_mutex_init(&m);
      49      428531 :             if(res)
      50             :             {
      51           0 :                 boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
      52             :             }
      53      428531 :         }
      54      428603 :         ~mutex()
      55      428603 :         {
      56      857206 :           BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
      57      428603 :         }
      58             : 
      59      715374 :         void lock() BOOST_THREAD_ACQUIRE()
      60             :         {
      61      715374 :             int res = posix::pthread_mutex_lock(&m);
      62      715374 :             if (res)
      63             :             {
      64           0 :                 boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
      65             :             }
      66      715374 :         }
      67             : 
      68      716250 :         void unlock() BOOST_THREAD_RELEASE()
      69             :         {
      70     1432500 :             BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
      71      716250 :         }
      72             : 
      73           0 :         bool try_lock() BOOST_THREAD_TRY_ACQUIRE(true)
      74             :         {
      75           0 :             int res = posix::pthread_mutex_trylock(&m);
      76           0 :             if (res==EBUSY)
      77             :             {
      78             :                 return false;
      79             :             }
      80             : 
      81           0 :             return !res;
      82             :         }
      83             : 
      84             : #define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE
      85             :         typedef pthread_mutex_t* native_handle_type;
      86             :         native_handle_type native_handle()
      87             :         {
      88             :             return &m;
      89             :         }
      90             : 
      91             : #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
      92             :         typedef unique_lock<mutex> scoped_lock;
      93             :         typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
      94             : #endif
      95             :     };
      96             : 
      97             :     typedef mutex try_mutex;
      98             : 
      99             :     class timed_mutex
     100             :     {
     101             :     private:
     102             :         pthread_mutex_t m;
     103             : #ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
     104             :         pthread_cond_t cond;
     105             :         bool is_locked;
     106             : #endif
     107             :     public:
     108             :         BOOST_THREAD_NO_COPYABLE(timed_mutex)
     109             :         timed_mutex()
     110             :         {
     111             :             int const res=posix::pthread_mutex_init(&m);
     112             :             if(res)
     113             :             {
     114             :                 boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
     115             :             }
     116             : #ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
     117             :             int const res2=posix::pthread_cond_init(&cond);
     118             :             if(res2)
     119             :             {
     120             :                 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
     121             :                 boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
     122             :             }
     123             :             is_locked=false;
     124             : #endif
     125             :         }
     126             :         ~timed_mutex()
     127             :         {
     128             :             BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
     129             : #ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
     130             :             BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
     131             : #endif
     132             :         }
     133             : 
     134             : #if defined BOOST_THREAD_USES_DATETIME
     135             :         template<typename TimeDuration>
     136             :         bool timed_lock(TimeDuration const & relative_time)
     137             :         {
     138             :             if (relative_time.is_pos_infinity())
     139             :             {
     140             :                 lock();
     141             :                 return true;
     142             :             }
     143             :             if (relative_time.is_special())
     144             :             {
     145             :                 return true;
     146             :             }
     147             :             detail::platform_duration d(relative_time);
     148             : #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
     149             :             const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
     150             :             d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
     151             :             while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
     152             :             {
     153             :               d = ts - detail::mono_platform_clock::now();
     154             :               if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
     155             :               d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
     156             :             }
     157             :             return true;
     158             : #else
     159             :             return do_try_lock_until(detail::internal_platform_clock::now() + d);
     160             : #endif
     161             :         }
     162             :         bool timed_lock(boost::xtime const & absolute_time)
     163             :         {
     164             :             return timed_lock(system_time(absolute_time));
     165             :         }
     166             : #endif
     167             : #ifdef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
     168             :         void lock()
     169             :         {
     170             :             int res = posix::pthread_mutex_lock(&m);
     171             :             if (res)
     172             :             {
     173             :                 boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
     174             :             }
     175             :         }
     176             : 
     177             :         void unlock()
     178             :         {
     179             :             BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
     180             :         }
     181             : 
     182             :         bool try_lock()
     183             :         {
     184             :           int res = posix::pthread_mutex_trylock(&m);
     185             :           if (res==EBUSY)
     186             :           {
     187             :               return false;
     188             :           }
     189             : 
     190             :           return !res;
     191             :         }
     192             : 
     193             : 
     194             :     private:
     195             :         bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
     196             :         {
     197             :           int const res=pthread_mutex_timedlock(&m,&timeout.getTs());
     198             :           BOOST_ASSERT(!res || res==ETIMEDOUT);
     199             :           return !res;
     200             :         }
     201             :     public:
     202             : 
     203             : #else
     204             :         void lock()
     205             :         {
     206             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     207             :             while(is_locked)
     208             :             {
     209             :                 BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
     210             :             }
     211             :             is_locked=true;
     212             :         }
     213             : 
     214             :         void unlock()
     215             :         {
     216             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     217             :             is_locked=false;
     218             :             BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
     219             :         }
     220             : 
     221             :         bool try_lock()
     222             :         {
     223             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     224             :             if(is_locked)
     225             :             {
     226             :                 return false;
     227             :             }
     228             :             is_locked=true;
     229             :             return true;
     230             :         }
     231             : 
     232             :     private:
     233             :         bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
     234             :         {
     235             :             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     236             :             while(is_locked)
     237             :             {
     238             :                 int const cond_res=posix::pthread_cond_timedwait(&cond,&m,&timeout.getTs());
     239             :                 if(cond_res==ETIMEDOUT)
     240             :                 {
     241             :                     break;
     242             :                 }
     243             :                 BOOST_ASSERT(!cond_res);
     244             :             }
     245             :             if(is_locked)
     246             :             {
     247             :                 return false;
     248             :             }
     249             :             is_locked=true;
     250             :             return true;
     251             :         }
     252             :     public:
     253             : #endif
     254             : 
     255             : #if defined BOOST_THREAD_USES_DATETIME
     256             :         bool timed_lock(system_time const & abs_time)
     257             :         {
     258             :             const detail::real_platform_timepoint ts(abs_time);
     259             : #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
     260             :             detail::platform_duration d(ts - detail::real_platform_clock::now());
     261             :             d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
     262             :             while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
     263             :             {
     264             :               d = ts - detail::real_platform_clock::now();
     265             :               if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
     266             :               d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
     267             :             }
     268             :             return true;
     269             : #else
     270             :             return do_try_lock_until(ts);
     271             : #endif
     272             :         }
     273             : #endif
     274             : #ifdef BOOST_THREAD_USES_CHRONO
     275             :         template <class Rep, class Period>
     276             :         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
     277             :         {
     278             :           return try_lock_until(chrono::steady_clock::now() + rel_time);
     279             :         }
     280             :         template <class Clock, class Duration>
     281             :         bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
     282             :         {
     283             :           typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
     284             :           common_duration d(t - Clock::now());
     285             :           d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
     286             :           while ( ! try_lock_until(detail::internal_chrono_clock::now() + d))
     287             :           {
     288             :               d = t - Clock::now();
     289             :               if ( d <= common_duration::zero() ) return false; // timeout occurred
     290             :               d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
     291             :           }
     292             :           return true;
     293             :         }
     294             :         template <class Duration>
     295             :         bool try_lock_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
     296             :         {
     297             :           detail::internal_platform_timepoint ts(t);
     298             :           return do_try_lock_until(ts);
     299             :         }
     300             : #endif
     301             : 
     302             : #define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
     303             :         typedef pthread_mutex_t* native_handle_type;
     304             :         native_handle_type native_handle()
     305             :         {
     306             :             return &m;
     307             :         }
     308             : 
     309             : #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
     310             :         typedef unique_lock<timed_mutex> scoped_timed_lock;
     311             :         typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
     312             :         typedef scoped_timed_lock scoped_lock;
     313             : #endif
     314             :     };
     315             : }
     316             : 
     317             : #include <boost/config/abi_suffix.hpp>
     318             : 
     319             : 
     320             : #endif

Generated by: LCOV version 1.14