Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
0002 #define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
0003 // (C) Copyright 2007-8 Anthony Williams
0004 // (C) Copyright 2011-2012 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 <pthread.h>
0010 #include <boost/throw_exception.hpp>
0011 #include <boost/thread/exceptions.hpp>
0012 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0013 #include <boost/thread/lock_types.hpp>
0014 #endif
0015 #include <boost/thread/thread_time.hpp>
0016 #include <boost/assert.hpp>
0017 #ifndef _WIN32
0018 #include <unistd.h>
0019 #endif
0020 #include <boost/date_time/posix_time/conversion.hpp>
0021 #include <errno.h>
0022 #include <boost/thread/detail/platform_time.hpp>
0023 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
0024 #include <boost/thread/pthread/pthread_helpers.hpp>
0025 #ifdef BOOST_THREAD_USES_CHRONO
0026 #include <boost/chrono/system_clocks.hpp>
0027 #include <boost/chrono/ceil.hpp>
0028 #endif
0029 #include <boost/thread/detail/delete.hpp>
0030 
0031 
0032 #if  defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
0033  ||  defined __ANDROID__
0034 #define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
0035 #endif
0036 
0037 #if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
0038 #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
0039 #endif
0040 
0041 #include <boost/config/abi_prefix.hpp>
0042 
0043 namespace boost
0044 {
0045     class recursive_mutex
0046     {
0047     private:
0048         pthread_mutex_t m;
0049 #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
0050         pthread_cond_t cond;
0051         bool is_locked;
0052         pthread_t owner;
0053         unsigned count;
0054 #endif
0055     public:
0056         BOOST_THREAD_NO_COPYABLE(recursive_mutex)
0057         recursive_mutex()
0058         {
0059 #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
0060             pthread_mutexattr_t attr;
0061 
0062             int const init_attr_res=pthread_mutexattr_init(&attr);
0063             if(init_attr_res)
0064             {
0065                 boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init"));
0066             }
0067             int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
0068             if(set_attr_res)
0069             {
0070                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
0071                 boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype"));
0072             }
0073 
0074             int const res=posix::pthread_mutex_init(&m,&attr);
0075             if(res)
0076             {
0077                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
0078                 boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
0079             }
0080             BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
0081 #else
0082             int const res=posix::pthread_mutex_init(&m);
0083             if(res)
0084             {
0085                 boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
0086             }
0087             int const res2=posix::pthread_cond_init(&cond);
0088             if(res2)
0089             {
0090                 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
0091                 boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
0092             }
0093             is_locked=false;
0094             count=0;
0095 #endif
0096         }
0097         ~recursive_mutex()
0098         {
0099             BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
0100 #ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
0101             BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
0102 #endif
0103         }
0104 
0105 #ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
0106         void lock()
0107         {
0108             BOOST_VERIFY(!posix::pthread_mutex_lock(&m));
0109         }
0110 
0111         void unlock()
0112         {
0113             BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
0114         }
0115 
0116         bool try_lock() BOOST_NOEXCEPT
0117         {
0118             int const res=posix::pthread_mutex_trylock(&m);
0119             BOOST_ASSERT(!res || res==EBUSY);
0120             return !res;
0121         }
0122 #define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE
0123         typedef pthread_mutex_t* native_handle_type;
0124         native_handle_type native_handle()
0125         {
0126             return &m;
0127         }
0128 
0129 #else
0130         void lock()
0131         {
0132             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0133             if(is_locked && pthread_equal(owner,pthread_self()))
0134             {
0135                 ++count;
0136                 return;
0137             }
0138 
0139             while(is_locked)
0140             {
0141                 BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
0142             }
0143             is_locked=true;
0144             ++count;
0145             owner=pthread_self();
0146         }
0147 
0148         void unlock()
0149         {
0150             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0151             if(!--count)
0152             {
0153                 is_locked=false;
0154             }
0155             BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
0156         }
0157 
0158         bool try_lock()
0159         {
0160             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0161             if(is_locked && !pthread_equal(owner,pthread_self()))
0162             {
0163                 return false;
0164             }
0165             is_locked=true;
0166             ++count;
0167             owner=pthread_self();
0168             return true;
0169         }
0170 
0171 #endif
0172 
0173 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0174         typedef unique_lock<recursive_mutex> scoped_lock;
0175         typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
0176 #endif
0177     };
0178 
0179     typedef recursive_mutex recursive_try_mutex;
0180 
0181     class recursive_timed_mutex
0182     {
0183     private:
0184         pthread_mutex_t m;
0185 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
0186         pthread_cond_t cond;
0187         bool is_locked;
0188         pthread_t owner;
0189         unsigned count;
0190 #endif
0191     public:
0192         BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
0193         recursive_timed_mutex()
0194         {
0195 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
0196             pthread_mutexattr_t attr;
0197 
0198             int const init_attr_res=pthread_mutexattr_init(&attr);
0199             if(init_attr_res)
0200             {
0201                 boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init"));
0202             }
0203             int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
0204             if(set_attr_res)
0205             {
0206                 boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype"));
0207             }
0208 
0209             int const res=posix::pthread_mutex_init(&m,&attr);
0210             if(res)
0211             {
0212                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
0213                 boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
0214             }
0215             BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
0216 #else
0217             int const res=posix::pthread_mutex_init(&m);
0218             if(res)
0219             {
0220                 boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
0221             }
0222             int const res2=posix::pthread_cond_init(&cond);
0223             if(res2)
0224             {
0225                 BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
0226                 boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
0227             }
0228             is_locked=false;
0229             count=0;
0230 #endif
0231         }
0232         ~recursive_timed_mutex()
0233         {
0234             BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
0235 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
0236             BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
0237 #endif
0238         }
0239 
0240 #if defined BOOST_THREAD_USES_DATETIME
0241         template<typename TimeDuration>
0242         bool timed_lock(TimeDuration const & relative_time)
0243         {
0244             if (relative_time.is_pos_infinity())
0245             {
0246                 lock();
0247                 return true;
0248             }
0249             if (relative_time.is_special())
0250             {
0251                 return true;
0252             }
0253             detail::platform_duration d(relative_time);
0254 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
0255             const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
0256             d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0257             while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
0258             {
0259               d = ts - detail::mono_platform_clock::now();
0260               if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
0261               d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0262             }
0263             return true;
0264 #else
0265             return do_try_lock_until(detail::internal_platform_clock::now() + d);
0266 #endif
0267         }
0268 #endif
0269 
0270 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
0271         void lock()
0272         {
0273             BOOST_VERIFY(!posix::pthread_mutex_lock(&m));
0274         }
0275 
0276         void unlock()
0277         {
0278             BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
0279         }
0280 
0281         bool try_lock()
0282         {
0283             int const res=posix::pthread_mutex_trylock(&m);
0284             BOOST_ASSERT(!res || res==EBUSY);
0285             return !res;
0286         }
0287     private:
0288         bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
0289         {
0290             int const res=pthread_mutex_timedlock(&m,&timeout.getTs());
0291             BOOST_ASSERT(!res || res==ETIMEDOUT);
0292             return !res;
0293         }
0294 
0295     public:
0296 
0297 #else
0298         void lock()
0299         {
0300             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0301             if(is_locked && pthread_equal(owner,pthread_self()))
0302             {
0303                 ++count;
0304                 return;
0305             }
0306 
0307             while(is_locked)
0308             {
0309                 BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
0310             }
0311             is_locked=true;
0312             ++count;
0313             owner=pthread_self();
0314         }
0315 
0316         void unlock()
0317         {
0318             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0319             if(!--count)
0320             {
0321                 is_locked=false;
0322             }
0323             BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
0324         }
0325 
0326         bool try_lock() BOOST_NOEXCEPT
0327         {
0328             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0329             if(is_locked && !pthread_equal(owner,pthread_self()))
0330             {
0331                 return false;
0332             }
0333             is_locked=true;
0334             ++count;
0335             owner=pthread_self();
0336             return true;
0337         }
0338 
0339     private:
0340         bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
0341         {
0342             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
0343             if(is_locked && pthread_equal(owner,pthread_self()))
0344             {
0345                 ++count;
0346                 return true;
0347             }
0348             while(is_locked)
0349             {
0350                 int const cond_res=posix::pthread_cond_timedwait(&cond,&m,&timeout.getTs());
0351                 if(cond_res==ETIMEDOUT)
0352                 {
0353                     break;
0354                 }
0355                 BOOST_ASSERT(!cond_res);
0356             }
0357             if(is_locked)
0358             {
0359                 return false;
0360             }
0361             is_locked=true;
0362             ++count;
0363             owner=pthread_self();
0364             return true;
0365         }
0366     public:
0367 
0368 #endif
0369 
0370 #if defined BOOST_THREAD_USES_DATETIME
0371         bool timed_lock(system_time const & abs_time)
0372         {
0373             const detail::real_platform_timepoint ts(abs_time);
0374 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
0375             detail::platform_duration d(ts - detail::real_platform_clock::now());
0376             d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0377             while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
0378             {
0379               d = ts - detail::real_platform_clock::now();
0380               if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
0381               d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
0382             }
0383             return true;
0384 #else
0385             return do_try_lock_until(ts);
0386 #endif
0387         }
0388 #endif
0389 #ifdef BOOST_THREAD_USES_CHRONO
0390         template <class Rep, class Period>
0391         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0392         {
0393           return try_lock_until(chrono::steady_clock::now() + rel_time);
0394         }
0395         template <class Clock, class Duration>
0396         bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
0397         {
0398           typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
0399           common_duration d(t - Clock::now());
0400           d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
0401           while ( ! try_lock_until(detail::internal_chrono_clock::now() + d))
0402           {
0403               d = t - Clock::now();
0404               if ( d <= common_duration::zero() ) return false; // timeout occurred
0405               d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
0406           }
0407           return true;
0408 
0409         }
0410         template <class Duration>
0411         bool try_lock_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
0412         {
0413           detail::internal_platform_timepoint ts(t);
0414           return do_try_lock_until(ts);
0415         }
0416 #endif
0417 
0418 #define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE
0419         typedef pthread_mutex_t* native_handle_type;
0420         native_handle_type native_handle()
0421         {
0422             return &m;
0423         }
0424 
0425 #if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0426         typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
0427         typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
0428         typedef scoped_timed_lock scoped_lock;
0429 #endif
0430     };
0431 
0432 }
0433 
0434 #include <boost/config/abi_suffix.hpp>
0435 
0436 #endif