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
0004
0005
0006
0007
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;
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;
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;
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