diff --git a/include/boost/thread/condition.hpp b/include/boost/thread/condition.hpp index e5a1c317..64889d56 100644 --- a/include/boost/thread/condition.hpp +++ b/include/boost/thread/condition.hpp @@ -1,5 +1,6 @@ // Copyright (C) 2001-2003 // William E. Kempf +// Copyright (C) 2007 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -61,6 +62,7 @@ public: // still waiting to be removed from m_queue #elif defined(BOOST_HAS_PTHREADS) pthread_cond_t m_condition; + pthread_mutex_t m_mutex; #elif defined(BOOST_HAS_MPTASKS) MPSemaphoreID m_gate; MPSemaphoreID m_queue; @@ -90,7 +92,7 @@ public: if (!lock) throw lock_error(); - do_wait(lock.m_mutex); + do_wait(*lock.mutex()); } template @@ -100,7 +102,7 @@ public: throw lock_error(); while (!pred()) - do_wait(lock.m_mutex); + do_wait(*lock.mutex()); } template @@ -109,7 +111,7 @@ public: if (!lock) throw lock_error(); - return do_timed_wait(lock.m_mutex, xt); + return do_timed_wait(*lock.mutex(), xt); } template @@ -120,7 +122,7 @@ public: while (!pred()) { - if (!do_timed_wait(lock.m_mutex, xt)) + if (!do_timed_wait(*lock.mutex(), xt)) return false; } @@ -135,25 +137,22 @@ private: { #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) m_impl.enter_wait(); +#else + pthread_mutex_lock(&m_impl.m_mutex); #endif - typedef detail::thread::lock_ops -#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG) -# define lock_ops lock_ops_ // HP confuses lock_ops witht the template -#endif - lock_ops; - - typename lock_ops::lock_state state; - lock_ops::unlock(mutex, state); + mutex.unlock(); #if defined(BOOST_HAS_PTHREADS) - m_impl.do_wait(state.pmutex); + m_impl.do_wait(&m_impl.m_mutex); #elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) m_impl.do_wait(); #endif - lock_ops::lock(mutex, state); -#undef lock_ops +#if defined(BOOST_HAS_PTHREADS) + pthread_mutex_unlock(&m_impl.m_mutex); +#endif + mutex.lock(); } template @@ -161,27 +160,24 @@ private: { #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) m_impl.enter_wait(); +#else + pthread_mutex_lock(&m_impl.m_mutex); #endif - typedef detail::thread::lock_ops -#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG) -# define lock_ops lock_ops_ // HP confuses lock_ops witht the template -#endif - lock_ops; - - typename lock_ops::lock_state state; - lock_ops::unlock(mutex, state); + mutex.unlock(); bool ret = false; #if defined(BOOST_HAS_PTHREADS) - ret = m_impl.do_timed_wait(xt, state.pmutex); + ret = m_impl.do_timed_wait(xt, &m_impl.m_mutex); #elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) ret = m_impl.do_timed_wait(xt); #endif - lock_ops::lock(mutex, state); -#undef lock_ops +#if defined(BOOST_HAS_PTHREADS) + pthread_mutex_unlock(&m_impl.m_mutex); +#endif + mutex.lock(); return ret; } diff --git a/include/boost/thread/locks.hpp b/include/boost/thread/locks.hpp new file mode 100644 index 00000000..258b0f60 --- /dev/null +++ b/include/boost/thread/locks.hpp @@ -0,0 +1,486 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +#ifndef BOOST_THREAD_LOCKS_HPP +#define BOOST_THREAD_LOCKS_HPP +#include +#include +#include +#include +#include + +namespace boost +{ + struct defer_lock_t + {}; + struct try_to_lock_t + {}; + struct adopt_lock_t + {}; + + const defer_lock_t defer_lock={}; + const try_to_lock_t try_to_lock={}; + const adopt_lock_t adopt_lock={}; + + template + class shareable_lock; + + template + class exclusive_lock; + + template + class upgradeable_lock; + + template + class lock_guard + { + private: + Mutex& m; + + explicit lock_guard(lock_guard&); + lock_guard& operator=(lock_guard&); + public: + explicit lock_guard(Mutex& m_): + m(m_) + { + m.lock(); + } + lock_guard(Mutex& m_,adopt_lock_t): + m(m_) + {} + ~lock_guard() + { + m.unlock(); + } + }; + + + template + class unique_lock + { + private: + Mutex* m; + bool is_locked; + explicit unique_lock(unique_lock&); + unique_lock& operator=(unique_lock&); + public: + explicit unique_lock(Mutex& m_): + m(&m_),is_locked(false) + { + lock(); + } + unique_lock(Mutex& m_,adopt_lock_t): + m(&m_),is_locked(true) + {} + unique_lock(Mutex& m_,defer_lock_t): + m(&m_),is_locked(false) + {} + unique_lock(Mutex& m_,try_to_lock_t): + m(&m_),is_locked(false) + { + try_lock(); + } + unique_lock(Mutex& m_,system_time const& target_time): + m(&m_),is_locked(false) + { + timed_lock(target_time); + } + unique_lock(boost::move_t other): + m(other->m),is_locked(other->is_locked) + { + other->is_locked=false; + } + unique_lock(boost::move_t > other); + + unique_lock& operator=(boost::move_t other) + { + unique_lock temp(other); + swap(temp); + return *this; + } + + unique_lock& operator=(boost::move_t > other) + { + unique_lock temp(other); + swap(temp); + return *this; + } + + void swap(unique_lock& other) + { + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); + } + void swap(boost::move_t other) + { + std::swap(m,other->m); + std::swap(is_locked,other->is_locked); + } + + ~unique_lock() + { + if(owns_lock()) + { + m->unlock(); + } + } + void lock() + { + if(owns_lock()) + { + throw boost::lock_error(); + } + m->lock(); + is_locked=true; + } + bool try_lock() + { + if(owns_lock()) + { + throw boost::lock_error(); + } + is_locked=m->try_lock(); + return is_locked; + } + template + bool timed_lock(TimeDuration const& relative_time) + { + is_locked=m->timed_lock(relative_time); + return is_locked; + } + + bool timed_lock(::boost::system_time const& absolute_time) + { + is_locked=m->timed_lock(absolute_time); + return is_locked; + } + void unlock() + { + if(!owns_lock()) + { + throw boost::lock_error(); + } + m->unlock(); + is_locked=false; + } + + typedef void (unique_lock::*bool_type)(); + operator bool_type() const + { + return is_locked?&unique_lock::lock:0; + } + bool owns_lock() const + { + return is_locked; + } + + Mutex* mutex() const + { + return m; + } + + Mutex* release() + { + Mutex* const res=m; + m=0; + is_locked=false; + return res; + } + + friend class shareable_lock; + friend class upgradeable_lock; + }; + + template + class shareable_lock + { + protected: + Mutex* m; + bool is_locked; + private: + explicit shareable_lock(shareable_lock&); + shareable_lock& operator=(shareable_lock&); + public: + explicit shareable_lock(Mutex& m_): + m(&m_),is_locked(false) + { + lock(); + } + shareable_lock(Mutex& m_,bool do_lock): + m(&m_),is_locked(false) + { + if(do_lock) + { + lock(); + } + } + shareable_lock(boost::move_t other): + m(other->m),is_locked(other->is_locked) + { + other->is_locked=false; + } + + shareable_lock(boost::move_t > other): + m(other->m),is_locked(other->is_locked) + { + other->is_locked=false; + if(is_locked) + { + m->unlock_and_lock_shareable(); + } + } + + shareable_lock(boost::move_t > other): + m(other->m),is_locked(other->is_locked) + { + other->is_locked=false; + if(is_locked) + { + m->unlock_upgradeable_and_lock_shareable(); + } + } + + shareable_lock& operator=(boost::move_t other) + { + shareable_lock temp(other); + swap(temp); + return *this; + } + + shareable_lock& operator=(boost::move_t > other) + { + shareable_lock temp(other); + swap(temp); + return *this; + } + + shareable_lock& operator=(boost::move_t > other) + { + shareable_lock temp(other); + swap(temp); + return *this; + } + + void swap(shareable_lock& other) + { + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); + } + + ~shareable_lock() + { + if(owns_lock()) + { + m->unlock_shareable(); + } + } + void lock() + { + if(owns_lock()) + { + throw boost::lock_error(); + } + m->lock_shareable(); + is_locked=true; + } + bool try_lock() + { + if(owns_lock()) + { + throw boost::lock_error(); + } + is_locked=m->try_lock_shareable(); + return is_locked; + } + void unlock() + { + if(!owns_lock()) + { + throw boost::lock_error(); + } + m->unlock_shareable(); + is_locked=false; + } + + typedef void (shareable_lock::*bool_type)(); + operator bool_type() const + { + return is_locked?&shareable_lock::lock:0; + } + bool owns_lock() const + { + return is_locked; + } + + }; + + template + class upgradeable_lock + { + protected: + Mutex* m; + bool is_locked; + private: + explicit upgradeable_lock(upgradeable_lock&); + upgradeable_lock& operator=(upgradeable_lock&); + public: + explicit upgradeable_lock(Mutex& m_): + m(&m_),is_locked(false) + { + lock(); + } + upgradeable_lock(Mutex& m_,bool do_lock): + m(&m_),is_locked(false) + { + if(do_lock) + { + lock(); + } + } + upgradeable_lock(boost::move_t other): + m(other->m),is_locked(other->is_locked) + { + other->is_locked=false; + } + + upgradeable_lock(boost::move_t > other): + m(other->m),is_locked(other->is_locked) + { + other->is_locked=false; + if(is_locked) + { + m->unlock_and_lock_upgradeable(); + } + } + + upgradeable_lock& operator=(boost::move_t other) + { + upgradeable_lock temp(other); + swap(temp); + return *this; + } + + upgradeable_lock& operator=(boost::move_t > other) + { + upgradeable_lock temp(other); + swap(temp); + return *this; + } + + void swap(upgradeable_lock& other) + { + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); + } + + ~upgradeable_lock() + { + if(owns_lock()) + { + m->unlock_upgradeable(); + } + } + void lock() + { + if(owns_lock()) + { + throw boost::lock_error(); + } + m->lock_upgradeable(); + is_locked=true; + } + bool try_lock() + { + if(owns_lock()) + { + throw boost::lock_error(); + } + is_locked=m->try_lock_upgradeable(); + return is_locked; + } + void unlock() + { + if(!owns_lock()) + { + throw boost::lock_error(); + } + m->unlock_upgradeable(); + is_locked=false; + } + + typedef void (upgradeable_lock::*bool_type)(); + operator bool_type() const + { + return is_locked?&upgradeable_lock::lock:0; + } + bool owns_lock() const + { + return is_locked; + } + friend class shareable_lock; + friend class unique_lock; + }; + + template + unique_lock::unique_lock(boost::move_t > other): + m(other->m),is_locked(other->is_locked) + { + other->is_locked=false; + if(is_locked) + { + m->unlock_upgradeable_and_lock(); + } + } + + template + class upgrade_to_unique_lock + { + private: + upgradeable_lock* source; + unique_lock exclusive; + + explicit upgrade_to_unique_lock(upgrade_to_unique_lock&); + upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&); + public: + explicit upgrade_to_unique_lock(upgradeable_lock& m_): + source(&m_),exclusive(boost::move(*source)) + {} + ~upgrade_to_unique_lock() + { + if(source) + { + *source=boost::move(exclusive); + } + } + + upgrade_to_unique_lock(boost::move_t other): + source(other->source),exclusive(boost::move(other->exclusive)) + { + other->source=0; + } + + upgrade_to_unique_lock& operator=(boost::move_t other) + { + upgrade_to_unique_lock temp(other); + swap(temp); + return *this; + } + void swap(upgrade_to_unique_lock& other) + { + std::swap(source,other.source); + exclusive.swap(other.exclusive); + } + typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&); + operator bool_type() const + { + return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0; + } + bool owns_lock() const + { + return exclusive.owns_lock(); + } + }; +} + +#endif diff --git a/include/boost/thread/mutex.hpp b/include/boost/thread/mutex.hpp index 1b74da55..98a1cbdd 100644 --- a/include/boost/thread/mutex.hpp +++ b/include/boost/thread/mutex.hpp @@ -1,170 +1,15 @@ -// Copyright (C) 2001-2003 -// William E. Kempf +#ifndef BOOST_THREAD_MUTEX_HPP +#define BOOST_THREAD_MUTEX_HPP + +// mutex.hpp // -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_MUTEX_WEK070601_HPP -#define BOOST_MUTEX_WEK070601_HPP +#include +#include BOOST_THREAD_PLATFORM(mutex.hpp) -#include - -#include -#include - -#if defined(BOOST_HAS_PTHREADS) -# include #endif - -#if defined(BOOST_HAS_MPTASKS) -# include "scoped_critical_region.hpp" -#endif - -namespace boost { - -struct xtime; -// disable warnings about non dll import -// see: http://www.boost.org/more/separate_compilation.html#dlls -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4251 4231 4660 4275) -#endif - -class BOOST_THREAD_DECL mutex - : private noncopyable -{ -public: - friend class detail::thread::lock_ops; - - typedef detail::thread::scoped_lock scoped_lock; - - mutex(); - ~mutex(); - -private: -#if defined(BOOST_HAS_WINTHREADS) - typedef void* cv_state; -#elif defined(BOOST_HAS_PTHREADS) - struct cv_state - { - pthread_mutex_t* pmutex; - }; -#elif defined(BOOST_HAS_MPTASKS) - struct cv_state - { - }; -#endif - void do_lock(); - void do_unlock(); - void do_lock(cv_state& state); - void do_unlock(cv_state& state); - -#if defined(BOOST_HAS_WINTHREADS) - void* m_mutex; - bool m_critical_section; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t m_mutex; -#elif defined(BOOST_HAS_MPTASKS) - threads::mac::detail::scoped_critical_region m_mutex; - threads::mac::detail::scoped_critical_region m_mutex_mutex; -#endif -}; - -class BOOST_THREAD_DECL try_mutex - : private noncopyable -{ -public: - friend class detail::thread::lock_ops; - - typedef detail::thread::scoped_lock scoped_lock; - typedef detail::thread::scoped_try_lock scoped_try_lock; - - try_mutex(); - ~try_mutex(); - -private: -#if defined(BOOST_HAS_WINTHREADS) - typedef void* cv_state; -#elif defined(BOOST_HAS_PTHREADS) - struct cv_state - { - pthread_mutex_t* pmutex; - }; -#elif defined(BOOST_HAS_MPTASKS) - struct cv_state - { - }; -#endif - void do_lock(); - bool do_trylock(); - void do_unlock(); - void do_lock(cv_state& state); - void do_unlock(cv_state& state); - -#if defined(BOOST_HAS_WINTHREADS) - void* m_mutex; - bool m_critical_section; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t m_mutex; -#elif defined(BOOST_HAS_MPTASKS) - threads::mac::detail::scoped_critical_region m_mutex; - threads::mac::detail::scoped_critical_region m_mutex_mutex; -#endif -}; - -class BOOST_THREAD_DECL timed_mutex - : private noncopyable -{ -public: - friend class detail::thread::lock_ops; - - typedef detail::thread::scoped_lock scoped_lock; - typedef detail::thread::scoped_try_lock scoped_try_lock; - typedef detail::thread::scoped_timed_lock scoped_timed_lock; - - timed_mutex(); - ~timed_mutex(); - -private: -#if defined(BOOST_HAS_WINTHREADS) - typedef void* cv_state; -#elif defined(BOOST_HAS_PTHREADS) - struct cv_state - { - pthread_mutex_t* pmutex; - }; -#elif defined(BOOST_HAS_MPTASKS) - struct cv_state - { - }; -#endif - void do_lock(); - bool do_trylock(); - bool do_timedlock(const xtime& xt); - void do_unlock(); - void do_lock(cv_state& state); - void do_unlock(cv_state& state); - -#if defined(BOOST_HAS_WINTHREADS) - void* m_mutex; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t m_mutex; - pthread_cond_t m_condition; - bool m_locked; -#elif defined(BOOST_HAS_MPTASKS) - threads::mac::detail::scoped_critical_region m_mutex; - threads::mac::detail::scoped_critical_region m_mutex_mutex; -#endif -}; -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif -} // namespace boost - -// Change Log: -// 8 Feb 01 WEKEMPF Initial version. -// 22 May 01 WEKEMPF Modified to use xtime for time outs. Factored out -// to three classes, mutex, try_mutex and timed_mutex. -// 3 Jan 03 WEKEMPF Modified for DLL implementation. - -#endif // BOOST_MUTEX_WEK070601_HPP diff --git a/include/boost/thread/once.hpp b/include/boost/thread/once.hpp index 7ff1464a..d29efe8f 100644 --- a/include/boost/thread/once.hpp +++ b/include/boost/thread/once.hpp @@ -10,19 +10,14 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#ifdef BOOST_HAS_MPTASKS -namespace boost { - -typedef long once_flag; -#define BOOST_ONCE_INIT 0 - -void call_once(once_flag& flag, void (*func)()); +#include BOOST_THREAD_PLATFORM(once.hpp) +namespace boost +{ + inline void call_once(void (*func)(),once_flag& flag) + { + call_once(flag,func); + } } -#else -#include BOOST_THREAD_PLATFORM(once.hpp) -#endif - - #endif diff --git a/include/boost/thread/pthread/mutex.hpp b/include/boost/thread/pthread/mutex.hpp new file mode 100644 index 00000000..09e5313b --- /dev/null +++ b/include/boost/thread/pthread/mutex.hpp @@ -0,0 +1,216 @@ +#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP +#define BOOST_THREAD_PTHREAD_MUTEX_HPP +// (C) Copyright 2007 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include "timespec.hpp" + +#ifdef _POSIX_TIMEOUTS +#if _POSIX_TIMEOUTS >= 0 +#define BOOST_PTHREAD_HAS_TIMEDLOCK +#endif +#endif + +namespace boost +{ + class mutex: + boost::noncopyable + { + private: + pthread_mutex_t m; + public: + mutex() + { + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + throw thread_resource_error(); + } + } + ~mutex() + { + int const res=pthread_mutex_destroy(&m); + BOOST_ASSERT(!res); + } + + void lock() + { + int const res=pthread_mutex_lock(&m); + BOOST_ASSERT(!res); + } + + void unlock() + { + int const res=pthread_mutex_unlock(&m); + BOOST_ASSERT(!res); + } + + bool try_lock() + { + int const res=pthread_mutex_trylock(&m); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } + typedef unique_lock scoped_lock; + typedef scoped_lock scoped_try_lock; + }; + + typedef mutex try_mutex; + + class timed_mutex: + boost::noncopyable + { + private: + pthread_mutex_t m; +#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK + pthread_cond_t cond; + bool is_locked; + + struct pthread_mutex_scoped_lock + { + pthread_mutex_t* m; + explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_): + m(m_) + { + int const res=pthread_mutex_lock(m); + BOOST_ASSERT(!res); + } + ~pthread_mutex_scoped_lock() + { + int const res=pthread_mutex_unlock(m); + BOOST_ASSERT(!res); + } + + }; + + +#endif + public: + timed_mutex() + { + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + throw thread_resource_error(); + } +#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + int const destroy_res=pthread_mutex_destroy(&m); + BOOST_ASSERT(!destroy_res); + throw thread_resource_error(); + } + is_locked=false; +#endif + } + ~timed_mutex() + { + int const res=pthread_mutex_destroy(&m); + BOOST_ASSERT(!res); +#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK + int const res2=pthread_cond_destroy(&cond); + BOOST_ASSERT(!res2); +#endif + } + + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } + +#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK + void lock() + { + int const res=pthread_mutex_lock(&m); + BOOST_ASSERT(!res); + } + + void unlock() + { + int const res=pthread_mutex_unlock(&m); + BOOST_ASSERT(!res); + } + + bool try_lock() + { + int const res=pthread_mutex_trylock(&m); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } + bool timed_lock(system_time const & abs_time) + { + struct timespec const timeout=detail::get_timespec(abs_time); + int const res=pthread_mutex_timedlock(&m,&timeout); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } +#else + void lock() + { + pthread_mutex_scoped_lock const _(&m); + while(is_locked) + { + int const cond_res=pthread_cond_wait(&cond,&m); + BOOST_ASSERT(!cond_res); + } + is_locked=true; + } + + void unlock() + { + pthread_mutex_scoped_lock const _(&m); + is_locked=false; + int const res=pthread_cond_signal(&cond); + BOOST_ASSERT(!res); + } + + bool try_lock() + { + pthread_mutex_scoped_lock const _(&m); + if(is_locked) + { + return false; + } + is_locked=true; + return true; + } + + bool timed_lock(system_time const & abs_time) + { + struct timespec const timeout=detail::get_timespec(abs_time); + pthread_mutex_scoped_lock const _(&m); + while(is_locked) + { + int const cond_res=pthread_cond_timewait(&cond,&m,&timeout); + if(cond_res==ETIMEOUT) + { + return false; + } + BOOST_ASSERT(!cond_res); + } + is_locked=true; + return true; + } +#endif + + typedef unique_lock scoped_timed_lock; + typedef scoped_timed_lock scoped_try_lock; + typedef scoped_timed_lock scoped_lock; + }; + +} + + +#endif diff --git a/include/boost/thread/pthread/recursive_mutex.hpp b/include/boost/thread/pthread/recursive_mutex.hpp new file mode 100644 index 00000000..2ccc3ae1 --- /dev/null +++ b/include/boost/thread/pthread/recursive_mutex.hpp @@ -0,0 +1,276 @@ +#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP +#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP +// (C) Copyright 2007 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "timespec.hpp" + +#ifdef _POSIX_TIMEOUTS +#if _POSIX_TIMEOUTS >= 0 +#define BOOST_PTHREAD_HAS_TIMEDLOCK +#endif +#endif + +namespace boost +{ + class recursive_mutex: + boost::noncopyable + { + private: + pthread_mutex_t m; + public: + recursive_mutex() + { + pthread_mutexattr_t attr; + + int const init_attr_res=pthread_mutexattr_init(&attr); + if(init_attr_res) + { + throw thread_resource_error(); + } + int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + if(set_attr_res) + { + throw thread_resource_error(); + } + + int const res=pthread_mutex_init(&m,&attr); + if(res) + { + throw thread_resource_error(); + } + int const destroy_attr_res=pthread_mutexattr_destroy(&attr); + BOOST_ASSERT(!destroy_attr_res); + } + ~recursive_mutex() + { + int const res=pthread_mutex_destroy(&m); + BOOST_ASSERT(!res); + } + + void lock() + { + int const res=pthread_mutex_lock(&m); + BOOST_ASSERT(!res); + } + + void unlock() + { + int const res=pthread_mutex_unlock(&m); + BOOST_ASSERT(!res); + } + + bool try_lock() + { + int const res=pthread_mutex_trylock(&m); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } + typedef unique_lock scoped_lock; + typedef scoped_lock scoped_try_lock; + }; + + typedef recursive_mutex recursive_try_mutex; + + class recursive_timed_mutex: + boost::noncopyable + { + private: + pthread_mutex_t m; +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK + pthread_cond_t cond; + bool is_locked; + pthread_t owner; + unsigned count; + + struct pthread_mutex_scoped_lock + { + pthread_mutex_t* m; + explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_): + m(m_) + { + int const res=pthread_mutex_lock(m); + BOOST_ASSERT(!res); + } + ~pthread_mutex_scoped_lock() + { + int const res=pthread_mutex_unlock(m); + BOOST_ASSERT(!res); + } + + }; + + +#endif + public: + recursive_timed_mutex() + { +#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK + pthread_mutexattr_t attr; + + int const init_attr_res=pthread_mutexattr_init(&attr); + if(init_attr_res) + { + throw thread_resource_error(); + } + int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + if(set_attr_res) + { + throw thread_resource_error(); + } + + int const res=pthread_mutex_init(&m,&attr); + if(res) + { + throw thread_resource_error(); + } + int const destroy_attr_res=pthread_mutexattr_destroy(&attr); + BOOST_ASSERT(!destroy_attr_res); +#else + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + throw thread_resource_error(); + } + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + int const destroy_res=pthread_mutex_destroy(&m); + BOOST_ASSERT(!destroy_res); + throw thread_resource_error(); + } + is_locked=false; + count=0; +#endif + } + ~recursive_timed_mutex() + { + int const res=pthread_mutex_destroy(&m); + BOOST_ASSERT(!res); +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK + int const res2=pthread_cond_destroy(&cond); + BOOST_ASSERT(!res2); +#endif + } + + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } + +#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK + void lock() + { + int const res=pthread_mutex_lock(&m); + BOOST_ASSERT(!res); + } + + void unlock() + { + int const res=pthread_mutex_unlock(&m); + BOOST_ASSERT(!res); + } + + bool try_lock() + { + int const res=pthread_mutex_trylock(&m); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } + bool timed_lock(system_time const & abs_time) + { + struct timespec const timeout=detail::get_timespec(abs_time); + int const res=pthread_mutex_timedlock(&m,&timeout); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } +#else + void lock() + { + pthread_mutex_scoped_lock const _(&m); + if(is_locked && owner==pthread_self()) + { + ++count; + return; + } + + while(is_locked) + { + int const cond_res=pthread_cond_wait(&cond,&m); + BOOST_ASSERT(!cond_res); + } + is_locked=true; + ++count; + owner=pthread_self(); + } + + void unlock() + { + pthread_mutex_scoped_lock const _(&m); + if(!--count) + { + is_locked=false; + } + int const res=pthread_cond_signal(&cond); + BOOST_ASSERT(!res); + } + + bool try_lock() + { + pthread_mutex_scoped_lock const _(&m); + if(is_locked && owner!=pthread_self()) + { + return false; + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } + + bool timed_lock(system_time const & abs_time) + { + struct timespec const timeout=detail::get_timespec(abs_time); + pthread_mutex_scoped_lock const _(&m); + if(is_locked && owner==pthread_self()) + { + ++count; + return; + } + while(is_locked) + { + int const cond_res=pthread_cond_timewait(&cond,&m,&timeout); + if(cond_res==ETIMEOUT) + { + return false; + } + BOOST_ASSERT(!cond_res); + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } +#endif + + typedef unique_lock scoped_timed_lock; + typedef scoped_timed_lock scoped_try_lock; + typedef scoped_timed_lock scoped_lock; + }; + +} + + +#endif diff --git a/include/boost/thread/pthread/timespec.hpp b/include/boost/thread/pthread/timespec.hpp new file mode 100644 index 00000000..a7039f7a --- /dev/null +++ b/include/boost/thread/pthread/timespec.hpp @@ -0,0 +1,23 @@ +#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP +#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP + +#include +#include + +namespace boost +{ + namespace detail + { + inline struct timespec get_timespec(boost::system_time const& abs_time) + { + struct timespec timeout={0}; + boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); + + timeout.tv_sec=time_since_epoch.total_seconds(); + timeout.tv_nsec=time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()); + return timeout; + } + } +} + +#endif diff --git a/include/boost/thread/recursive_mutex.hpp b/include/boost/thread/recursive_mutex.hpp index a7efa48f..f01ae11b 100644 --- a/include/boost/thread/recursive_mutex.hpp +++ b/include/boost/thread/recursive_mutex.hpp @@ -1,184 +1,15 @@ -// Copyright (C) 2001-2003 -// William E. Kempf +#ifndef BOOST_THREAD_RECURSIVE_MUTEX_HPP +#define BOOST_THREAD_RECURSIVE_MUTEX_HPP + +// recursive_mutex.hpp // -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP -#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP +#include +#include BOOST_THREAD_PLATFORM(recursive_mutex.hpp) -#include - -#include -#include - -#if defined(BOOST_HAS_PTHREADS) -# include #endif - -#if defined(BOOST_HAS_MPTASKS) -# include "scoped_critical_region.hpp" -#endif - -namespace boost { - -struct xtime; -// disable warnings about non dll import -// see: http://www.boost.org/more/separate_compilation.html#dlls -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4251 4231 4660 4275) -#endif -class BOOST_THREAD_DECL recursive_mutex - : private noncopyable -{ -public: - friend class detail::thread::lock_ops; - - typedef detail::thread::scoped_lock scoped_lock; - - recursive_mutex(); - ~recursive_mutex(); - -private: -#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) - typedef std::size_t cv_state; -#elif defined(BOOST_HAS_PTHREADS) - struct cv_state - { - long count; - pthread_mutex_t* pmutex; - }; -#endif - void do_lock(); - void do_unlock(); - void do_lock(cv_state& state); - void do_unlock(cv_state& state); - -#if defined(BOOST_HAS_WINTHREADS) - void* m_mutex; - bool m_critical_section; - unsigned long m_count; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t m_mutex; - unsigned m_count; -# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - pthread_cond_t m_unlocked; - pthread_t m_thread_id; - bool m_valid_id; -# endif -#elif defined(BOOST_HAS_MPTASKS) - threads::mac::detail::scoped_critical_region m_mutex; - threads::mac::detail::scoped_critical_region m_mutex_mutex; - std::size_t m_count; -#endif -}; - -class BOOST_THREAD_DECL recursive_try_mutex - : private noncopyable -{ -public: - friend class detail::thread::lock_ops; - - typedef detail::thread::scoped_lock scoped_lock; - typedef detail::thread::scoped_try_lock< - recursive_try_mutex> scoped_try_lock; - - recursive_try_mutex(); - ~recursive_try_mutex(); - -private: -#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) - typedef std::size_t cv_state; -#elif defined(BOOST_HAS_PTHREADS) - struct cv_state - { - long count; - pthread_mutex_t* pmutex; - }; -#endif - void do_lock(); - bool do_trylock(); - void do_unlock(); - void do_lock(cv_state& state); - void do_unlock(cv_state& state); - -#if defined(BOOST_HAS_WINTHREADS) - void* m_mutex; - bool m_critical_section; - unsigned long m_count; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t m_mutex; - unsigned m_count; -# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - pthread_cond_t m_unlocked; - pthread_t m_thread_id; - bool m_valid_id; -# endif -#elif defined(BOOST_HAS_MPTASKS) - threads::mac::detail::scoped_critical_region m_mutex; - threads::mac::detail::scoped_critical_region m_mutex_mutex; - std::size_t m_count; -#endif -}; - -class BOOST_THREAD_DECL recursive_timed_mutex - : private noncopyable -{ -public: - friend class detail::thread::lock_ops; - - typedef detail::thread::scoped_lock scoped_lock; - typedef detail::thread::scoped_try_lock< - recursive_timed_mutex> scoped_try_lock; - typedef detail::thread::scoped_timed_lock< - recursive_timed_mutex> scoped_timed_lock; - - recursive_timed_mutex(); - ~recursive_timed_mutex(); - -private: -#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) - typedef std::size_t cv_state; -#elif defined(BOOST_HAS_PTHREADS) - struct cv_state - { - long count; - pthread_mutex_t* pmutex; - }; -#endif - void do_lock(); - bool do_trylock(); - bool do_timedlock(const xtime& xt); - void do_unlock(); - void do_lock(cv_state& state); - void do_unlock(cv_state& state); - -#if defined(BOOST_HAS_WINTHREADS) - void* m_mutex; - unsigned long m_count; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t m_mutex; - pthread_cond_t m_unlocked; - pthread_t m_thread_id; - bool m_valid_id; - unsigned m_count; -#elif defined(BOOST_HAS_MPTASKS) - threads::mac::detail::scoped_critical_region m_mutex; - threads::mac::detail::scoped_critical_region m_mutex_mutex; - std::size_t m_count; -#endif -}; -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif -} // namespace boost - -#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP - -// Change Log: -// 8 Feb 01 WEKEMPF Initial version. -// 1 Jun 01 WEKEMPF Modified to use xtime for time outs. Factored out -// to three classes, mutex, try_mutex and timed_mutex. -// 11 Jun 01 WEKEMPF Modified to use PTHREAD_MUTEX_RECURSIVE if available. -// 3 Jan 03 WEKEMPF Modified for DLL implementation. diff --git a/include/boost/thread/thread_time.hpp b/include/boost/thread/thread_time.hpp new file mode 100644 index 00000000..8c735977 --- /dev/null +++ b/include/boost/thread/thread_time.hpp @@ -0,0 +1,40 @@ +#ifndef BOOST_THREAD_TIME_HPP +#define BOOST_THREAD_TIME_HPP +#include +#include + +namespace boost +{ + typedef boost::posix_time::ptime system_time; + + inline system_time get_system_time() + { + return boost::date_time::microsec_clock::universal_time(); + } + + namespace detail + { + inline system_time get_system_time_sentinel() + { + return system_time(boost::posix_time::pos_infin); + } + + inline unsigned get_milliseconds_until(system_time const& target_time) + { + if(target_time.is_pos_infinity()) + { + return ~0u; + } + system_time const now=get_system_time(); + if(target_time<=now) + { + return 0; + } + return (target_time-now).total_milliseconds(); + } + + } + +} + +#endif diff --git a/include/boost/thread/win32/basic_recursive_mutex.hpp b/include/boost/thread/win32/basic_recursive_mutex.hpp new file mode 100644 index 00000000..e5f79981 --- /dev/null +++ b/include/boost/thread/win32/basic_recursive_mutex.hpp @@ -0,0 +1,120 @@ +#ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP +#define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP + +// basic_recursive_mutex.hpp +// +// (C) Copyright 2006-7 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "thread_primitives.hpp" +#include "basic_timed_mutex.hpp" + +namespace boost +{ + namespace detail + { + template + struct basic_recursive_mutex_impl + { + long recursion_count; + long locking_thread_id; + underlying_mutex_type mutex; + + void initialize() + { + recursion_count=0; + locking_thread_id=0; + mutex.initialize(); + } + + void destroy() + { + mutex.destroy(); + } + + bool try_lock() + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id); + } + + void lock() + { + long const current_thread_id=win32::GetCurrentThreadId(); + if(!try_recursive_lock(current_thread_id)) + { + mutex.lock(); + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + } + } + bool timed_lock(::boost::system_time const& target) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target); + } + long get_active_count() + { + return mutex.get_active_count(); + } + + void unlock() + { + if(!--recursion_count) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0); + mutex.unlock(); + } + } + + bool locked() + { + return mutex.locked(); + } + + private: + bool try_recursive_lock(long current_thread_id) + { + if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id) + { + ++recursion_count; + return true; + } + return false; + } + + bool try_basic_lock(long current_thread_id) + { + if(mutex.try_lock()) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + + bool try_timed_lock(long current_thread_id,::boost::system_time const& target) + { + if(mutex.timed_lock(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + + }; + + typedef basic_recursive_mutex_impl basic_recursive_mutex; + typedef basic_recursive_mutex_impl basic_recursive_timed_mutex; + } +} + +#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0} + +#endif diff --git a/include/boost/thread/win32/basic_timed_mutex.hpp b/include/boost/thread/win32/basic_timed_mutex.hpp new file mode 100644 index 00000000..bc2b1af0 --- /dev/null +++ b/include/boost/thread/win32/basic_timed_mutex.hpp @@ -0,0 +1,157 @@ +#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP +#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP + +// basic_timed_mutex_win32.hpp +// +// (C) Copyright 2006 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include "thread_primitives.hpp" +#include "interlocked_read.hpp" +#include + +namespace boost +{ + namespace detail + { + struct basic_timed_mutex + { + BOOST_STATIC_CONSTANT(long,lock_flag_value=0x80000000); + long active_count; + void* event; + + void initialize() + { + active_count=0; + event=0; + } + + void destroy() + { + void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0); + if(old_event) + { + win32::CloseHandle(old_event); + } + } + + + bool try_lock() + { + long old_count=active_count&~lock_flag_value; + do + { + long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count); + if(current_count==old_count) + { + return true; + } + old_count=current_count; + } + while(!(old_count&lock_flag_value)); + return false; + } + + void lock() + { + bool const success=timed_lock(::boost::detail::get_system_time_sentinel()); + BOOST_ASSERT(success); + } + bool timed_lock(::boost::system_time const& wait_until) + { + long old_count=active_count; + while(true) + { + long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count); + if(current_count==old_count) + { + break; + } + old_count=current_count; + } + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + ++old_count; // we're waiting, too + do + { + old_count-=(lock_flag_value+1); // there will be one less active thread on this mutex when it gets unlocked + if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0) + { + BOOST_INTERLOCKED_DECREMENT(&active_count); + return false; + } + do + { + long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,old_count|lock_flag_value,old_count); + if(current_count==old_count) + { + break; + } + old_count=current_count; + } + while(!(old_count&lock_flag_value)); + lock_acquired=!(old_count&lock_flag_value); + } + while(!lock_acquired); + } + return true; + } + + long get_active_count() + { + return ::boost::detail::interlocked_read_acquire(&active_count); + } + + void unlock() + { + long const offset=lock_flag_value+1; + long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,-offset); + + if(old_count>offset) + { + win32::SetEvent(get_event()); + } + } + + bool locked() + { + return get_active_count()>=lock_flag_value; + } + + private: + void* get_event() + { + void* current_event=::boost::detail::interlocked_read_acquire(&event); + + if(!current_event) + { + void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset); + void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0); + if(old_event!=0) + { + win32::CloseHandle(new_event); + return old_event; + } + else + { + return new_event; + } + } + return current_event; + } + + }; + + } +} + +#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0} + +#endif diff --git a/include/boost/thread/win32/interlocked_read.hpp b/include/boost/thread/win32/interlocked_read.hpp index 98f0b3e6..77a333ba 100644 --- a/include/boost/thread/win32/interlocked_read.hpp +++ b/include/boost/thread/win32/interlocked_read.hpp @@ -9,7 +9,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifdef BOOST_MSVC extern "C" void _ReadWriteBarrier(void); #pragma intrinsic(_ReadWriteBarrier) @@ -33,4 +33,26 @@ namespace boost } } +#else + +#include + +namespace boost +{ + namespace detail + { + inline long interlocked_read_acquire(long volatile* x) + { + return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0); + } + inline void* interlocked_read_acquire(void* volatile* x) + { + return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0); + } + } +} + +#endif + + #endif diff --git a/include/boost/thread/win32/mutex.hpp b/include/boost/thread/win32/mutex.hpp new file mode 100644 index 00000000..29759a9a --- /dev/null +++ b/include/boost/thread/win32/mutex.hpp @@ -0,0 +1,61 @@ +#ifndef BOOST_THREAD_WIN32_MUTEX_HPP +#define BOOST_THREAD_WIN32_MUTEX_HPP +// (C) Copyright 2005-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "basic_timed_mutex.hpp" +#include +#include +#include + +namespace boost +{ + namespace detail + { + typedef ::boost::detail::basic_timed_mutex underlying_mutex; + } + + class mutex: + boost::noncopyable, + public ::boost::detail::underlying_mutex + { + public: + mutex() + { + initialize(); + } + ~mutex() + { + destroy(); + } + + typedef unique_lock scoped_lock; + typedef scoped_lock scoped_try_lock; + }; + + typedef mutex try_mutex; + + class timed_mutex: + boost::noncopyable, + public ::boost::detail::basic_timed_mutex + { + public: + timed_mutex() + { + initialize(); + } + + ~timed_mutex() + { + destroy(); + } + + typedef unique_lock scoped_timed_lock; + typedef scoped_timed_lock scoped_try_lock; + typedef scoped_timed_lock scoped_lock; + }; +} + +#endif diff --git a/include/boost/thread/win32/recursive_mutex.hpp b/include/boost/thread/win32/recursive_mutex.hpp new file mode 100644 index 00000000..855dd15b --- /dev/null +++ b/include/boost/thread/win32/recursive_mutex.hpp @@ -0,0 +1,61 @@ +#ifndef BOOST_RECURSIVE_MUTEX_WIN32_HPP +#define BOOST_RECURSIVE_MUTEX_WIN32_HPP + +// recursive_mutex.hpp +// +// (C) Copyright 2006-7 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include +#include "basic_recursive_mutex.hpp" +#include +#include + +namespace boost +{ + class recursive_mutex: + boost::noncopyable, + public ::boost::detail::basic_recursive_mutex + { + public: + recursive_mutex() + { + ::boost::detail::basic_recursive_mutex::initialize(); + } + ~recursive_mutex() + { + ::boost::detail::basic_recursive_mutex::destroy(); + } + + typedef unique_lock scoped_lock; + typedef scoped_lock scoped_try_lock; + }; + + typedef recursive_mutex recursive_try_mutex; + + class recursive_timed_mutex: + boost::noncopyable, + public ::boost::detail::basic_recursive_timed_mutex + { + public: + recursive_timed_mutex() + { + ::boost::detail::basic_recursive_timed_mutex::initialize(); + } + ~recursive_timed_mutex() + { + ::boost::detail::basic_recursive_timed_mutex::destroy(); + } + + typedef unique_lock scoped_timed_lock; + typedef scoped_timed_lock scoped_try_lock; + typedef scoped_timed_lock scoped_lock; + }; +} + + +#endif diff --git a/include/boost/thread/win32/thread_primitives.hpp b/include/boost/thread/win32/thread_primitives.hpp index 2213c7b8..6ada6ae4 100644 --- a/include/boost/thread/win32/thread_primitives.hpp +++ b/include/boost/thread/win32/thread_primitives.hpp @@ -113,13 +113,21 @@ namespace boost inline handle create_anonymous_event(event_type type,initial_event_state state) { handle const res=CreateEventA(0,type,state,0); - return res?res:throw thread_resource_error(); + if(!res) + { + throw thread_resource_error(); + } + return res; } inline handle create_anonymous_semaphore(long initial_count,long max_count) { handle const res=CreateSemaphoreA(NULL,initial_count,max_count,NULL); - return res?res:throw thread_resource_error(); + if(!res) + { + throw thread_resource_error(); + } + return res; } inline handle duplicate_handle(handle source) @@ -128,7 +136,11 @@ namespace boost long const same_access_flag=2; handle new_handle=0; bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0; - return success?new_handle:throw thread_resource_error(); + if(!success) + { + throw thread_resource_error(); + } + return new_handle; } inline void release_semaphore(handle semaphore,long count)