Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:29:21

0001 #ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
0002 #define BOOST_THREAD_PTHREAD_MUTEX_HPP
0003 // (C) Copyright 2007-8 Anthony Williams
0004 // (C) Copyright 2011,2012,2015 Vicente J. Botet Escriba
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #include <boost/thread/detail/config.hpp>
0010 #include <boost/assert.hpp>
0011 #include <pthread.h>
0012 #include <boost/throw_exception.hpp>
0013 #include <boost/core/ignore_unused.hpp>
0014 #include <boost/thread/exceptions.hpp>
0015 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0016 #include <boost/thread/lock_types.hpp>
0017 #endif
0018 #include <boost/thread/thread_time.hpp>
0019 #if defined BOOST_THREAD_USES_DATETIME
0020 #include <boost/thread/xtime.hpp>
0021 #endif
0022 #include <boost/assert.hpp>
0023 #include <errno.h>
0024 #include <boost/thread/detail/platform_time.hpp>
0025 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
0026 #include <boost/thread/pthread/pthread_helpers.hpp>
0027 #ifdef BOOST_THREAD_USES_CHRONO
0028 #include <boost/chrono/system_clocks.hpp>
0029 #include <boost/chrono/ceil.hpp>
0030 #endif
0031 #include <boost/thread/detail/delete.hpp>
0032 
0033 
0034 #include <boost/config/abi_prefix.hpp>
0035 
0036 namespace boost
0037 {
0038 
0039     class BOOST_THREAD_CAPABILITY("mutex") mutex
0040     {
0041     private:
0042         pthread_mutex_t m;
0043     public:
0044         BOOST_THREAD_NO_COPYABLE(mutex)
0045 
0046         mutex()
0047         {
0048             int const res=posix::pthread_mutex_init(&m);
0049             if(res)
0050             {
0051                 boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
0052             }
0053         }
0054         ~mutex()
0055         {
0056           BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
0057         }
0058 
0059         void lock() BOOST_THREAD_ACQUIRE()
0060         {
0061             int res = posix::pthread_mutex_lock(&m);
0062             if (res)
0063             {
0064                 boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
0065             }
0066         }
0067 
0068         void unlock() BOOST_THREAD_RELEASE()
0069         {
0070             BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
0071         }
0072 
0073         bool try_lock() BOOST_THREAD_TRY_ACQUIRE(true)
0074         {
0075             int res = posix::pthread_mutex_trylock(&m);
0076             if (res==EBUSY)
0077             {
0078                 return false;
0079             }
0080 
0081             return !res;
0082         }
0083 
0084 #define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE
0085         typedef pthread_mutex_t* native_handle_type;
0086         native_handle_type native_handle()
0087         {
0088             return &m;
0089         }
0090 
0091 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0092         typedef unique_lock<mutex> scoped_lock;
0093         typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
0094 #endif
0095     };
0096 
0097     typedef mutex try_mutex;
0098 
0099     class timed_mutex
0100     {
0101     private:
0102         pthread_mutex_t m;
0103 #ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
0104         pthread_cond_t cond;
0105         bool is_locked;
0106 #endif
0107     public:
0108         BOOST_THREAD_NO_COPYABLE(timed_mutex)
0109         timed_mutex()
0110         {
0111             int const res=posix::pthread_mutex_init(&m);
0112             if(res)
0113             {
0114                 boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
0115             }
0116 #ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
0117             int const res2=posix::pthread_cond_init(&cond);
0118             if(res2)
0119             {
0120                 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
0121                 boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
0122             }
0123             is_locked=false;
0124 #endif
0125         }
0126         ~timed_mutex()
0127         {
0128             BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
0129 #ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
0130             BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
0131 #endif
0132         }
0133 
0134 #if defined BOOST_THREAD_USES_DATETIME
0135         template<typename TimeDuration>
0136         bool timed_lock(TimeDuration const & relative_time)
0137         {
0138             if (relative_time.is_pos_infinity())
0139             {
0140                 lock();
0141                 return true;
0142             }
0143             if (relative_time.is_special())
0144             {
0145                 return true;
0146             }
0147             detail::platform_duration d(relative_time);
0148 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
0149             const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
0150             d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0151             while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
0152             {
0153               d = ts - detail::mono_platform_clock::now();
0154               if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
0155               d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0156             }
0157             return true;
0158 #else
0159             return do_try_lock_until(detail::internal_platform_clock::now() + d);
0160 #endif
0161         }
0162         bool timed_lock(boost::xtime const & absolute_time)
0163         {
0164             return timed_lock(system_time(absolute_time));
0165         }
0166 #endif
0167 #ifdef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
0168         void lock()
0169         {
0170             int res = posix::pthread_mutex_lock(&m);
0171             if (res)
0172             {
0173                 boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
0174             }
0175         }
0176 
0177         void unlock()
0178         {
0179             BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
0180         }
0181 
0182         bool try_lock()
0183         {
0184           int res = posix::pthread_mutex_trylock(&m);
0185           if (res==EBUSY)
0186           {
0187               return false;
0188           }
0189 
0190           return !res;
0191         }
0192 
0193 
0194     private:
0195         bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
0196         {
0197           int const res=pthread_mutex_timedlock(&m,&timeout.getTs());
0198           BOOST_ASSERT(!res || res==ETIMEDOUT);
0199           return !res;
0200         }
0201     public:
0202 
0203 #else
0204         void lock()
0205         {
0206             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0207             while(is_locked)
0208             {
0209                 BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
0210             }
0211             is_locked=true;
0212         }
0213 
0214         void unlock()
0215         {
0216             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0217             is_locked=false;
0218             BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
0219         }
0220 
0221         bool try_lock()
0222         {
0223             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0224             if(is_locked)
0225             {
0226                 return false;
0227             }
0228             is_locked=true;
0229             return true;
0230         }
0231 
0232     private:
0233         bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
0234         {
0235             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0236             while(is_locked)
0237             {
0238                 int const cond_res=posix::pthread_cond_timedwait(&cond,&m,&timeout.getTs());
0239                 if(cond_res==ETIMEDOUT)
0240                 {
0241                     break;
0242                 }
0243                 BOOST_ASSERT(!cond_res);
0244             }
0245             if(is_locked)
0246             {
0247                 return false;
0248             }
0249             is_locked=true;
0250             return true;
0251         }
0252     public:
0253 #endif
0254 
0255 #if defined BOOST_THREAD_USES_DATETIME
0256         bool timed_lock(system_time const & abs_time)
0257         {
0258             const detail::real_platform_timepoint ts(abs_time);
0259 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
0260             detail::platform_duration d(ts - detail::real_platform_clock::now());
0261             d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0262             while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
0263             {
0264               d = ts - detail::real_platform_clock::now();
0265               if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
0266               d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0267             }
0268             return true;
0269 #else
0270             return do_try_lock_until(ts);
0271 #endif
0272         }
0273 #endif
0274 #ifdef BOOST_THREAD_USES_CHRONO
0275         template <class Rep, class Period>
0276         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0277         {
0278           return try_lock_until(chrono::steady_clock::now() + rel_time);
0279         }
0280         template <class Clock, class Duration>
0281         bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
0282         {
0283           typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
0284           common_duration d(t - Clock::now());
0285           d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
0286           while ( ! try_lock_until(detail::internal_chrono_clock::now() + d))
0287           {
0288               d = t - Clock::now();
0289               if ( d <= common_duration::zero() ) return false; // timeout occurred
0290               d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
0291           }
0292           return true;
0293         }
0294         template <class Duration>
0295         bool try_lock_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
0296         {
0297           detail::internal_platform_timepoint ts(t);
0298           return do_try_lock_until(ts);
0299         }
0300 #endif
0301 
0302 #define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
0303         typedef pthread_mutex_t* native_handle_type;
0304         native_handle_type native_handle()
0305         {
0306             return &m;
0307         }
0308 
0309 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0310         typedef unique_lock<timed_mutex> scoped_timed_lock;
0311         typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
0312         typedef scoped_timed_lock scoped_lock;
0313 #endif
0314     };
0315 }
0316 
0317 #include <boost/config/abi_suffix.hpp>
0318 
0319 
0320 #endif