diff --git a/example/starvephil/starvephil.cpp b/example/starvephil/starvephil.cpp index 0ea755c7..675d4bb6 100644 --- a/example/starvephil/starvephil.cpp +++ b/example/starvephil/starvephil.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include diff --git a/example/tennis/tennis.cpp b/example/tennis/tennis.cpp index 54ae3214..7f2d207e 100644 --- a/example/tennis/tennis.cpp +++ b/example/tennis/tennis.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/thread/condition.hpp b/include/boost/thread/condition.hpp index 38e4f7a5..7192b4e2 100644 --- a/include/boost/thread/condition.hpp +++ b/include/boost/thread/condition.hpp @@ -1,25 +1,16 @@ -/* - * - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 22 May 01 Modified to use xtime for time outs. - * 23 May 01 Removed "duration" timed_waits, as they are too difficult - * to use with spurious wakeups. - */ - -#ifndef BOOST_CONDITION_HPP -#define BOOST_CONDITION_HPP +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_CONDITION_WEK070601_HPP +#define BOOST_CONDITION_WEK070601_HPP #include #ifndef BOOST_HAS_THREADS @@ -27,130 +18,138 @@ #endif #include -#include #if defined(BOOST_HAS_PTHREADS) # include #endif -namespace boost +namespace boost { + +struct xtime; + +class condition : private noncopyable { - class condition : private noncopyable +public: + condition(); + ~condition(); + + void notify_one(); + void notify_all(); + + template + void wait(L& lock) { - public: - condition(); - ~condition(); + if (!lock) + throw lock_error(); - void notify_one(); - void notify_all(); + do_wait(lock.m_mutex); + } - template - void wait(L& lock) + template + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_error(); + + while (!pred()) + do_wait(lock.m_mutex); + } + + template + bool timed_wait(L& lock, const xtime& xt) + { + if (!lock) + throw lock_error(); + + return do_timed_wait(lock.m_mutex, xt); + } + + template + bool timed_wait(L& lock, const xtime& xt, Pr pred) + { + if (!lock) + throw lock_error(); + + while (!pred()) { - if (!lock) - throw lock_error(); - - do_wait(lock._mutex); + if (!do_timed_wait(lock.m_mutex, xt)) + return false; } - template - void wait(L& lock, Pr pred) - { - if (!lock) - throw lock_error(); - - while (!pred()) - do_wait(lock._mutex); - } + return true; + } - template - bool timed_wait(L& lock, const xtime& xt) - { - if (!lock) - throw lock_error(); - - return do_timed_wait(lock._mutex, xt); - } - - template - bool timed_wait(L& lock, const xtime& xt, Pr pred) - { - if (!lock) - throw lock_error(); - - while (!pred()) - { - if (!do_timed_wait(lock._mutex, xt)) - return false; - } - - return true; - } - - private: - template - void do_wait(M& mutex) - { +private: + template + void do_wait(M& mutex) + { #if defined(BOOST_HAS_WINTHREADS) - enter_wait(); + enter_wait(); #endif - typename M::cv_state state; - mutex.do_unlock(state); + typename M::cv_state state; + mutex.do_unlock(state); #if defined(BOOST_HAS_PTHREADS) - do_wait(state.pmutex); + do_wait(state.pmutex); #elif defined(BOOST_HAS_WINTHREADS) - do_wait(); + do_wait(); #endif - mutex.do_lock(state); - } + mutex.do_lock(state); + } - template - bool do_timed_wait(M& mutex, const xtime& xt) - { + template + bool do_timed_wait(M& mutex, const xtime& xt) + { #if defined(BOOST_HAS_WINTHREADS) - enter_wait(); + enter_wait(); #endif - typename M::cv_state state; - mutex.do_unlock(state); + typename M::cv_state state; + mutex.do_unlock(state); - bool ret = false; + bool ret = false; #if defined(BOOST_HAS_PTHREADS) - ret = do_timed_wait(xt, state.pmutex); + ret = do_timed_wait(xt, state.pmutex); #elif defined(BOOST_HAS_WINTHREADS) - ret = do_timed_wait(xt); + ret = do_timed_wait(xt); #endif - mutex.do_lock(state); + mutex.do_lock(state); - return ret; - } + return ret; + } #if defined(BOOST_HAS_WINTHREADS) - void enter_wait(); - void do_wait(); - bool do_timed_wait(const xtime& xt); + void enter_wait(); + void do_wait(); + bool do_timed_wait(const xtime& xt); #elif defined(BOOST_HAS_PTHREADS) - void do_wait(pthread_mutex_t* pmutex); - bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex); + void do_wait(pthread_mutex_t* pmutex); + bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex); #endif #if defined(BOOST_HAS_WINTHREADS) - unsigned long _gate; - unsigned long _queue; - unsigned long _mutex; - unsigned _gone; // # threads that timed out and never made it to the _queue - long _blocked; // # threads _blocked _waiting for the condition - unsigned _waiting; // # threads _waiting no longer _waiting for the condition but still - // _waiting to be removed from the _queue + unsigned long m_gate; + unsigned long m_queue; + unsigned long m_mutex; + unsigned m_gone; // # threads that timed out and never made it to the m_queue + long m_blocked; // # threads m_blocked m_waiting for the condition + unsigned m_waiting; // # threads m_waiting no longer m_waiting for the condition but still + // m_waiting to be removed from the m_queue #elif defined(BOOST_HAS_PTHREADS) - pthread_cond_t _cond; + pthread_cond_t m_condition; #endif - }; +}; + } // namespace boost -#endif // BOOST_CONDITION_HPP +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. +// 22 May 01 WEKEMPF Modified to use xtime for time outs. +// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too difficult +// to use with spurious wakeups. + +#endif // BOOST_CONDITION_WEK070601_HPP diff --git a/include/boost/thread/config.hpp b/include/boost/thread/config.hpp index 6fd00edf..5276d4ee 100644 --- a/include/boost/thread/config.hpp +++ b/include/boost/thread/config.hpp @@ -1,3 +1,14 @@ +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + // This file is used to configure Boost.Threads during development // in order to decouple dependency on any Boost release. Once // accepted into Boost these contents will be moved to @@ -5,8 +16,8 @@ // #include statements will be changed // accordingly. -#ifndef BOOST_THREAD_CONFIG_HPP -#define BOOST_THREAD_CONFIG_HPP +#ifndef BOOST_THREAD_CONFIG_WEK070601_HPP +#define BOOST_THREAD_CONFIG_WEK070601_HPP #include @@ -52,7 +63,7 @@ # if defined(_MT) # define BOOST_HAS_THREADS # endif -# define BOOST_HAS_WINTHREADS // comment out this to test pthreads-win32. +//# define BOOST_HAS_WINTHREADS // comment out this to test pthreads-win32. # if !defined(BOOST_HAS_WINTHREADS) # define BOOST_HAS_PTHREADS # define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE @@ -62,4 +73,4 @@ # define BOOST_HAS_FTIME #endif -#endif \ No newline at end of file +#endif // BOOST_THREAD_CONFIG_WEK070601_HPP \ No newline at end of file diff --git a/include/boost/thread/mutex.hpp b/include/boost/thread/mutex.hpp index 7e9d3ece..d4f316ae 100644 --- a/include/boost/thread/mutex.hpp +++ b/include/boost/thread/mutex.hpp @@ -1,23 +1,16 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 22 May 01 Modified to use xtime for time outs. Factored out - * to three classes, mutex, try_mutex and timed_mutex. - */ - -#ifndef BOOST_MUTEX_HPP -#define BOOST_MUTEX_HPP +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_MUTEX_WEK070601_HPP +#define BOOST_MUTEX_WEK070601_HPP #include #ifndef BOOST_HAS_THREADS @@ -25,123 +18,129 @@ #endif #include -#include #include #if defined(BOOST_HAS_PTHREADS) # include #endif -namespace boost +namespace boost { + +class condition; +struct xtime; + +class mutex : private noncopyable { - class condition; +public: + friend class basic_lock; + friend class condition; - class mutex : private noncopyable + typedef basic_lock lock; + + mutex(); + ~mutex(); + +private: +#if defined(BOOST_HAS_WINTHREADS) + typedef void* cv_state; +#elif defined(BOOST_HAS_PTHREADS) + struct cv_state { - public: - friend class basic_lock; - friend class condition; - - typedef basic_lock 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; - }; -#endif - void do_lock(); - void do_unlock(); - void do_lock(cv_state& state); - void do_unlock(cv_state& state); - -#if defined(BOOST_HAS_WINTHREADS) - unsigned long _mutex; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t _mutex; -#endif + pthread_mutex_t* pmutex; }; +#endif + void do_lock(); + void do_unlock(); + void do_lock(cv_state& state); + void do_unlock(cv_state& state); - class try_mutex : private noncopyable +#if defined(BOOST_HAS_WINTHREADS) + unsigned long m_mutex; +#elif defined(BOOST_HAS_PTHREADS) + pthread_mutex_t m_mutex; +#endif +}; + +class try_mutex : private noncopyable +{ +public: + friend class basic_lock; + friend class basic_trylock; + friend class condition; + + typedef basic_lock lock; + typedef basic_trylock trylock; + + try_mutex(); + ~try_mutex(); + +private: +#if defined(BOOST_HAS_WINTHREADS) + typedef void* cv_state; +#elif defined(BOOST_HAS_PTHREADS) + struct cv_state { - public: - friend class basic_lock; - friend class basic_trylock; - friend class condition; - - typedef basic_lock lock; - typedef basic_trylock trylock; - - 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; - }; -#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) - unsigned long _mutex; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t _mutex; -#endif + 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); - class timed_mutex : private noncopyable +#if defined(BOOST_HAS_WINTHREADS) + unsigned long m_mutex; +#elif defined(BOOST_HAS_PTHREADS) + pthread_mutex_t m_mutex; +#endif +}; + +class timed_mutex : private noncopyable +{ +public: + friend class basic_lock; + friend class basic_trylock; + friend class basic_timedlock; + friend class condition; + + typedef basic_lock lock; + typedef basic_trylock trylock; + typedef basic_timedlock timedlock; + + timed_mutex(); + ~timed_mutex(); + +private: +#if defined(BOOST_HAS_WINTHREADS) + typedef void* cv_state; +#elif defined(BOOST_HAS_PTHREADS) + struct cv_state { - public: - friend class basic_lock; - friend class basic_trylock; - friend class basic_timedlock; - friend class condition; - - typedef basic_lock lock; - typedef basic_trylock trylock; - typedef basic_timedlock timedlock; - - 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; - }; -#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) - unsigned long _mutex; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t _mutex; - pthread_cond_t _cond; - bool _locked; -#endif + 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) + unsigned long m_mutex; +#elif defined(BOOST_HAS_PTHREADS) + pthread_mutex_t m_mutex; + pthread_cond_t m_condition; + bool m_locked; +#endif +}; + } // namespace boost -#endif // BOOST_MUTEX_HPP +// 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. + +#endif // BOOST_MUTEX_WEK070601_HPP diff --git a/include/boost/thread/recursive_mutex.hpp b/include/boost/thread/recursive_mutex.hpp index f44bf131..3eb36814 100644 --- a/include/boost/thread/recursive_mutex.hpp +++ b/include/boost/thread/recursive_mutex.hpp @@ -1,24 +1,16 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 1 Jun 01 Modified to use xtime for time outs. Factored out - * to three classes, mutex, try_mutex and timed_mutex. - * 11 Jun 01 Modified to use PTHREAD_MUTEX_RECURSIVE if available. - */ - -#ifndef BOOST_RECURSIVE_MUTEX_HPP -#define BOOST_RECURSIVE_MUTEX_HPP +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP +#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP #include #ifndef BOOST_HAS_THREADS @@ -32,136 +24,144 @@ # include #endif -namespace boost +namespace boost { + +class condition; +struct xtime; + +class recursive_mutex : private noncopyable { - class condition; +public: + friend class basic_lock; + friend class condition; - class recursive_mutex : private noncopyable - { - public: - friend class basic_lock; - friend class condition; - - typedef basic_lock lock; - - recursive_mutex(); - ~recursive_mutex(); - - private: + typedef basic_lock lock; + + recursive_mutex(); + ~recursive_mutex(); + +private: #if defined(BOOST_HAS_WINTHREADS) - typedef size_t cv_state; + typedef size_t cv_state; #elif defined(BOOST_HAS_PTHREADS) - struct cv_state - { - long count; - pthread_mutex_t* pmutex; - }; + 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); + void do_lock(); + void do_unlock(); + void do_lock(cv_state& state); + void do_unlock(cv_state& state); #if defined(BOOST_HAS_WINTHREADS) - unsigned long _mutex; - unsigned long _count; + unsigned long m_mutex; + unsigned long m_count; #elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t _mutex; - unsigned _count; + pthread_mutex_t m_mutex; + unsigned m_count; # if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - pthread_cond_t _unlocked; - pthread_t _thread_id; - bool _valid_id; + pthread_cond_t m_unlocked; + pthread_t m_thread_id; + bool m_valid_id; # endif #endif - }; +}; - class recursive_try_mutex : private noncopyable +class recursive_try_mutex : private noncopyable +{ +public: + friend class basic_lock; + friend class basic_trylock; + friend class condition; + + typedef basic_lock lock; + typedef basic_trylock trylock; + + recursive_try_mutex(); + ~recursive_try_mutex(); + +private: +#if defined(BOOST_HAS_WINTHREADS) + typedef size_t cv_state; +#elif defined(BOOST_HAS_PTHREADS) + struct cv_state { - public: - friend class basic_lock; - friend class basic_trylock; - friend class condition; - - typedef basic_lock lock; - typedef basic_trylock trylock; - - recursive_try_mutex(); - ~recursive_try_mutex(); - - private: -#if defined(BOOST_HAS_WINTHREADS) - typedef size_t cv_state; -#elif defined(BOOST_HAS_PTHREADS) - struct cv_state - { - long count; - pthread_mutex_t* pmutex; - }; + 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); - + 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) - unsigned long _mutex; - unsigned long _count; + unsigned long m_mutex; + unsigned long m_count; #elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t _mutex; - unsigned _count; + pthread_mutex_t m_mutex; + unsigned m_count; # if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - pthread_cond_t _unlocked; - pthread_t _thread_id; - bool _valid_id; + pthread_cond_t m_unlocked; + pthread_t m_thread_id; + bool m_valid_id; # endif #endif - }; +}; - class recursive_timed_mutex : private noncopyable +class recursive_timed_mutex : private noncopyable +{ +public: + friend class basic_lock; + friend class basic_trylock; + friend class basic_timedlock; + friend class condition; + + typedef basic_lock lock; + typedef basic_trylock trylock; + typedef basic_timedlock timedlock; + + recursive_timed_mutex(); + ~recursive_timed_mutex(); + +private: +#if defined(BOOST_HAS_WINTHREADS) + typedef size_t cv_state; +#elif defined(BOOST_HAS_PTHREADS) + struct cv_state { - public: - friend class basic_lock; - friend class basic_trylock; - friend class basic_timedlock; - friend class condition; - - typedef basic_lock lock; - typedef basic_trylock trylock; - typedef basic_timedlock timedlock; - - recursive_timed_mutex(); - ~recursive_timed_mutex(); - - private: -#if defined(BOOST_HAS_WINTHREADS) - typedef 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) - unsigned long _mutex; - unsigned long _count; -#elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t _mutex; - pthread_cond_t _unlocked; - pthread_t _thread_id; - bool _valid_id; - unsigned _count; -#endif + 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) + unsigned long 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; +#endif +}; + } // namespace boost -#endif // BOOST_RECURSIVE_MUTEX_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. + +#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP diff --git a/include/boost/thread/semaphore.hpp b/include/boost/thread/semaphore.hpp index 773e6e8a..1855e691 100644 --- a/include/boost/thread/semaphore.hpp +++ b/include/boost/thread/semaphore.hpp @@ -1,23 +1,16 @@ -/* - * - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 22 May 01 Modified to use xtime for time outs. - */ - -#ifndef BOOST_SEMAPHORE_HPP -#define BOOST_SEMAPHORE_HPP +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_SEMAPHORE_WEK070601_HPP +#define BOOST_SEMAPHORE_WEK070601_HPP #include #ifndef BOOST_HAS_THREADS @@ -25,33 +18,40 @@ #endif #include -#include #if defined(BOOST_HAS_PTHREADS) # include #endif namespace boost { - class semaphore : private noncopyable - { - public: - explicit semaphore(unsigned count=0, unsigned max=0); - ~semaphore(); - - bool up(unsigned count=1, unsigned* prev=0); - void down(); - bool down(const xtime& xt); - - private: + +struct xtime; + +class semaphore : private noncopyable +{ +public: + explicit semaphore(unsigned count=0, unsigned max=0); + ~semaphore(); + + bool up(unsigned count=1, unsigned* prev=0); + void down(); + bool down(const xtime& xt); + +private: #if defined(BOOST_HAS_WINTHREADS) - unsigned long _sema; + unsigned long m_sema; #elif defined(BOOST_HAS_PTHREADS) - pthread_mutex_t _mutex; - pthread_cond_t _cond; - unsigned _available; - unsigned _max; + pthread_mutex_t m_mutex; + pthread_cond_t m_condition; + unsigned m_available; + unsigned m_max; #endif - }; +}; + } // namespace boost -#endif // BOOST_SEMAPHORE_HPP +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. +// 22 May 01 WEKEMPF Modified to use xtime for time outs. + +#endif // BOOST_SEMAPHORE_WEK070601_HPP diff --git a/include/boost/thread/thread.hpp b/include/boost/thread/thread.hpp index 820057a4..777da9ad 100644 --- a/include/boost/thread/thread.hpp +++ b/include/boost/thread/thread.hpp @@ -1,23 +1,16 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 1 Jun 01 Added boost::thread initial implementation. - * 3 Jul 01 Redesigned boost::thread to be noncopyable. - */ - -#ifndef BOOST_THREAD_HPP -#define BOOST_THREAD_HPP +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_THREAD_WEK070601_HPP +#define BOOST_THREAD_WEK070601_HPP #include #ifndef BOOST_HAS_THREADS @@ -26,7 +19,6 @@ #include #include -#include #include #include #include @@ -36,62 +28,70 @@ # include #endif -namespace boost +namespace boost { + +struct xtime; + +class lock_error : public std::runtime_error { - class lock_error : public std::runtime_error - { - public: - lock_error(); - }; +public: + lock_error(); +}; - class thread : boost::noncopyable - { - public: - thread(); - thread(const boost::function0& threadfunc); - ~thread(); +class thread : private noncopyable +{ +public: + thread(); + thread(const function0& threadfunc); + ~thread(); - bool operator==(const thread& other); - bool operator!=(const thread& other); + bool operator==(const thread& other) const; + bool operator!=(const thread& other) const; - void join(); - bool try_join(); - bool timed_join(const xtime& xt); + void join(); + bool try_join(); + bool timed_join(const xtime& xt); - static void sleep(const xtime& xt); - static void yield(); + static void sleep(const xtime& xt); + static void yield(); - private: +private: #if defined(BOOST_HAS_WINTHREADS) - unsigned long m_thread; - unsigned int m_id; + unsigned long m_thread; + unsigned int m_id; #elif defined(BOOST_HAS_PTHREADS) - class thread_list; - friend class thread_list; + class thread_list; + friend class thread_list; - pthread_t m_thread; - mutex m_mutex; - condition m_cond; - bool m_alive; - thread_list* m_list; + pthread_t m_thread; + mutex m_mutex; + condition m_condition; + bool m_alive; + thread_list* m_state_manager; #endif - }; +}; - class thread_group : boost::noncopyable - { - public: - thread_group(); - ~thread_group(); +class thread_group : private noncopyable +{ +public: + thread_group(); + ~thread_group(); - thread* create_thread(const boost::function0& threadfunc); - void add_thread(thread* thrd); - void remove_thread(thread* thrd); - void join_all(); + thread* create_thread(const function0& threadfunc); + void add_thread(thread* thrd); + void remove_thread(thread* thrd); + void join_all(); + +private: + std::list m_threads; + mutex m_mutex; +}; - private: - std::list m_threads; - mutex m_mutex; - }; } // namespace boost -#endif // BOOST_THREAD_HPP +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. +// 1 Jun 01 WEKEMPF Added boost::thread initial implementation. +// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable. + +#endif // BOOST_THREAD_WEK070601_HPP diff --git a/include/boost/thread/tss.hpp b/include/boost/thread/tss.hpp index a6c00370..b50ffc79 100644 --- a/include/boost/thread/tss.hpp +++ b/include/boost/thread/tss.hpp @@ -1,49 +1,50 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 6 Jun 01 Initial version. - */ - -#ifndef BOOST_TSS_HPP -#define BOOST_TSS_HPP +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_TSS_WEK070601_HPP +#define BOOST_TSS_WEK070601_HPP #include #ifndef BOOST_HAS_THREADS # error Thread support is unavailable! #endif +#include + #if defined(BOOST_HAS_PTHREADS) # include #endif -namespace boost +namespace boost { + +class tss : private noncopyable { - class tss - { - public: - tss(); - ~tss(); +public: + tss(); + ~tss(); - void* get() const; - bool set(void* value); + void* get() const; + bool set(void* value); - private: +private: #if defined(BOOST_HAS_WINTHREADS) - unsigned long _key; + unsigned long m_key; #elif defined(BOOST_HAS_PTHREADS) - pthread_key_t _key; + pthread_key_t m_key; #endif - }; -} +}; -#endif // BOOST_TSS_HPP \ No newline at end of file +} // namespace boost + +// Change Log: +// 6 Jun 01 WEKEMPF Initial version. + +#endif // BOOST_TSS_WEK070601_HPP \ No newline at end of file diff --git a/include/boost/thread/xlock.hpp b/include/boost/thread/xlock.hpp index e23ba53e..40430bb9 100644 --- a/include/boost/thread/xlock.hpp +++ b/include/boost/thread/xlock.hpp @@ -1,162 +1,162 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 22 May 01 Modified to use xtime for time outs. - */ - -#ifndef BOOST_XLOCK_HPP -#define BOOST_XLOCK_HPP +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_XLOCK_WEK070601_HPP +#define BOOST_XLOCK_WEK070601_HPP -#include #include namespace boost { - class condition; + +class condition; +struct xtime; + +template +class basic_lock : private noncopyable +{ +public: + friend class condition; - template - class basic_lock : noncopyable - { - public: - friend class condition; - - typedef M mutex_type; - - explicit basic_lock(M& mx, bool lock_it=true) - : _mutex(mx), _locked(false) - { - if (lock_it) lock(); - } - ~basic_lock() - { - if (_locked) unlock(); - } - - void lock() - { - if (_locked) throw lock_error(); - _mutex.do_lock(); - _locked = true; - } - void unlock() - { - if (!_locked) throw lock_error(); - _mutex.do_unlock(); - _locked = false; - } - - operator const void*() const { return _locked ? this : 0; } - - private: - M& _mutex; - bool _locked; - }; + typedef M mutex_type; - template - class basic_trylock : private noncopyable + explicit basic_lock(M& mx, bool lock_it=true) + : m_mutex(mx), m_locked(false) { - public: - friend class condition; - - typedef M mutex_type; - - explicit basic_trylock(M& mx) - : _mutex(mx), _locked(false) - { - try_lock(); - } - basic_trylock(M& mx, bool lock_it) - : _mutex(mx), _locked(false) - { - if (lock_it) lock(); - } - ~basic_trylock() - { - if (_locked) unlock(); - } - - void lock() - { - if (_locked) throw lock_error(); - _mutex.do_lock(); - _locked = true; - } - bool try_lock() - { - if (_locked) throw lock_error(); - return (_locked = _mutex.do_trylock()); - } - void unlock() - { - if (!_locked) throw lock_error(); - _mutex.do_unlock(); - _locked = false; - } - - operator const void*() const { return _locked ? this : 0; } - - private: - M& _mutex; - bool _locked; - }; + if (lock_it) lock(); + } + ~basic_lock() + { + if (m_locked) unlock(); + } - template - class basic_timedlock : private noncopyable + void lock() { - public: - friend class condition; - - typedef M mutex_type; - - basic_timedlock(M& mx, const xtime& xt) - : _mutex(mx), _locked(false) - { - timed_lock(xt); - } - basic_timedlock(M& mx, bool lock_it) - : _mutex(mx), _locked(false) - { - if (lock_it) lock(); - } - ~basic_timedlock() - { - if (_locked) unlock(); - } - - void lock() - { - if (_locked) throw lock_error(); - _mutex.do_lock(); - _locked = true; - } - bool timed_lock(const xtime& xt) - { - if (_locked) throw lock_error(); - return (_locked = _mutex.do_timedlock(xt)); - } - void unlock() - { - if (!_locked) throw lock_error(); - _mutex.do_unlock(); - _locked = false; - } - - operator const void*() const { return _locked ? this : 0; } - - private: - M& _mutex; - bool _locked; - }; + if (m_locked) throw lock_error(); + m_mutex.do_lock(); + m_locked = true; + } + void unlock() + { + if (!m_locked) throw lock_error(); + m_mutex.do_unlock(); + m_locked = false; + } + + operator const void*() const { return m_locked ? this : 0; } + +private: + M& m_mutex; + bool m_locked; +}; + +template +class basic_trylock : private noncopyable +{ +public: + friend class condition; + + typedef M mutex_type; + + explicit basic_trylock(M& mx) + : m_mutex(mx), m_locked(false) + { + try_lock(); + } + basic_trylock(M& mx, bool lock_it) + : m_mutex(mx), m_locked(false) + { + if (lock_it) lock(); + } + ~basic_trylock() + { + if (m_locked) unlock(); + } + + void lock() + { + if (m_locked) throw lock_error(); + m_mutex.do_lock(); + m_locked = true; + } + bool try_lock() + { + if (m_locked) throw lock_error(); + return (m_locked = m_mutex.do_trylock()); + } + void unlock() + { + if (!m_locked) throw lock_error(); + m_mutex.do_unlock(); + m_locked = false; + } + + operator const void*() const { return m_locked ? this : 0; } + +private: + M& m_mutex; + bool m_locked; +}; + +template +class basic_timedlock : private noncopyable +{ +public: + friend class condition; + + typedef M mutex_type; + + basic_timedlock(M& mx, const xtime& xt) + : m_mutex(mx), m_locked(false) + { + timed_lock(xt); + } + basic_timedlock(M& mx, bool lock_it) + : m_mutex(mx), m_locked(false) + { + if (lock_it) lock(); + } + ~basic_timedlock() + { + if (m_locked) unlock(); + } + + void lock() + { + if (m_locked) throw lock_error(); + m_mutex.do_lock(); + m_locked = true; + } + bool timed_lock(const xtime& xt) + { + if (m_locked) throw lock_error(); + return (m_locked = m_mutex.do_timedlock(xt)); + } + void unlock() + { + if (!m_locked) throw lock_error(); + m_mutex.do_unlock(); + m_locked = false; + } + + operator const void*() const { return m_locked ? this : 0; } + +private: + M& m_mutex; + bool m_locked; +}; + } // namespace boost -#endif // BOOST_XLOCK_HPP +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. +// 22 May 01 WEKEMPF Modified to use xtime for time outs. + +#endif // BOOST_XLOCK_WEK070601_HPP diff --git a/include/boost/thread/xtime.hpp b/include/boost/thread/xtime.hpp index b323640a..5163f672 100644 --- a/include/boost/thread/xtime.hpp +++ b/include/boost/thread/xtime.hpp @@ -1,49 +1,48 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - */ - -#ifndef BOOST_XTIME_HPP -#define BOOST_XTIME_HPP +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_XTIME_WEK070601_HPP +#define BOOST_XTIME_WEK070601_HPP #include -namespace boost +namespace boost { + +enum { - enum - { - TIME_UTC=1, - TIME_TAI, - TIME_MONOTONIC, - TIME_PROCESS, - TIME_THREAD, - TIME_LOCAL, - TIME_SYNC, - TIME_RESOLUTION - }; + TIME_UTC=1, + TIME_TAI, + TIME_MONOTONIC, + TIME_PROCESS, + TIME_THREAD, + TIME_LOCAL, + TIME_SYNC, + TIME_RESOLUTION +}; - struct xtime - { +struct xtime +{ #if defined(BOOST_NO_INT64_T) - int_fast32_t sec; + int_fast32_t sec; #else - int_fast64_t sec; + int_fast64_t sec; #endif - int_fast32_t nsec; - }; + int_fast32_t nsec; +}; - int xtime_get(struct xtime* xtp, int clock_type); -} +int xtime_get(struct xtime* xtp, int clock_type); -#endif // BOOST_XTIME_HPP \ No newline at end of file +} // namespace boost + +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. + +#endif // BOOST_XTIME_WEK070601_HPP \ No newline at end of file diff --git a/src/condition.cpp b/src/condition.cpp index 2b684ca5..08eaeb6f 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -1,23 +1,17 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 22 May 01 Modified to use xtime for time outs. - */ +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +#include #include #include -#include #include #include #include "timeconv.inl" @@ -28,312 +22,317 @@ # include #endif -namespace boost -{ +namespace boost { + #if defined(BOOST_HAS_WINTHREADS) - condition::condition() - : _gone(0), _blocked(0), _waiting(0) +condition::condition() + : m_gone(0), m_blocked(0), m_waiting(0) +{ + m_gate = reinterpret_cast(CreateSemaphore(0, 1, 1, 0)); + m_queue = reinterpret_cast(CreateSemaphore(0, 0, std::numeric_limits::max(), 0)); + m_mutex = reinterpret_cast(CreateMutex(0, 0, 0)); + + if (!m_gate || !m_queue || !m_mutex) { - _gate = reinterpret_cast(CreateSemaphore(0, 1, 1, 0)); - _queue = reinterpret_cast(CreateSemaphore(0, 0, std::numeric_limits::max(), 0)); - _mutex = reinterpret_cast(CreateMutex(0, 0, 0)); + int res = CloseHandle(reinterpret_cast(m_gate)); + assert(res); + res = CloseHandle(reinterpret_cast(m_queue)); + assert(res); + res = CloseHandle(reinterpret_cast(m_mutex)); + assert(res); - if (!_gate || !_queue || !_mutex) + throw std::runtime_error("boost::condition : failure to construct"); + } +} + +condition::~condition() +{ + int res = CloseHandle(reinterpret_cast(m_gate)); + assert(res); + res = CloseHandle(reinterpret_cast(m_queue)); + assert(res); + res = CloseHandle(reinterpret_cast(m_mutex)); + assert(res); +} + +void condition::notify_one() +{ + unsigned signals = 0; + + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + + if (m_waiting != 0) // the m_gate is already closed + { + if (m_blocked == 0) { - int res = CloseHandle(reinterpret_cast(_gate)); - assert(res); - res = CloseHandle(reinterpret_cast(_queue)); - assert(res); - res = CloseHandle(reinterpret_cast(_mutex)); + res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); + return; + } - throw std::runtime_error("boost::condition : failure to construct"); + ++m_waiting; + --m_blocked = 0; + } + else + { + res = WaitForSingleObject(reinterpret_cast(m_gate), INFINITE); + assert(res == WAIT_OBJECT_0); + if (m_blocked > m_gone) + { + if (m_gone != 0) + { + m_blocked -= m_gone; + m_gone = 0; + } + signals = m_waiting = 1; + --m_blocked; + } + else + { + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); + assert(res); + } + + res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); + + if (signals) + { + res = ReleaseSemaphore(reinterpret_cast(m_queue), signals, 0); + assert(res); } } +} + +void condition::notify_all() +{ + unsigned signals = 0; + + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + + if (m_waiting != 0) // the m_gate is already closed + { + if (m_blocked == 0) + { + res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); + return; + } + + m_waiting += (signals = m_blocked); + m_blocked = 0; + } + else + { + res = WaitForSingleObject(reinterpret_cast(m_gate), INFINITE); + assert(res == WAIT_OBJECT_0); + if (m_blocked > m_gone) + { + if (m_gone != 0) + { + m_blocked -= m_gone; + m_gone = 0; + } + signals = m_waiting = m_blocked; + m_blocked = 0; + } + else + { + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); + assert(res); + } + + res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); + + if (signals) + { + res = ReleaseSemaphore(reinterpret_cast(m_queue), signals, 0); + assert(res); + } + } +} + +void condition::enter_wait() +{ + int res = WaitForSingleObject(reinterpret_cast(m_gate), INFINITE); + assert(res == WAIT_OBJECT_0); + ++m_blocked; + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); + assert(res); +} + +void condition::do_wait() +{ + int res = WaitForSingleObject(reinterpret_cast(m_queue), INFINITE); + assert(res == WAIT_OBJECT_0); - condition::~condition() + unsigned was_waiting=0; + unsigned was_gone=0; + + res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + was_waiting = m_waiting; + was_gone = m_gone; + if (was_waiting != 0) { - int res = CloseHandle(reinterpret_cast(_gate)); + if (--m_waiting == 0) + { + if (m_blocked != 0) + { + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); // open m_gate + assert(res); + was_waiting = 0; + } + else if (m_gone != 0) + m_gone = 0; + } + } + else if (++m_gone == (std::numeric_limits::max() / 2)) + { + // timeout occured, normalize the m_gone count + // this may occur if many calls to wait with a timeout are made and + // no call to notify_* is made + res = WaitForSingleObject(reinterpret_cast(m_gate), INFINITE); + assert(res == WAIT_OBJECT_0); + m_blocked -= m_gone; + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); assert(res); - res = CloseHandle(reinterpret_cast(_queue)); - assert(res); - res = CloseHandle(reinterpret_cast(_mutex)); + m_gone = 0; + } + res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); + + if (was_waiting == 1) + { + for (/**/ ; was_gone; --was_gone) + { + // better now than spurious later + res = WaitForSingleObject(reinterpret_cast(m_queue), INFINITE); + assert(res == WAIT_OBJECT_0); + } + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); assert(res); } +} - void condition::notify_one() +bool condition::do_timed_wait(const xtime& xt) +{ + unsigned milliseconds; + to_duration(xt, milliseconds); + + int res = WaitForSingleObject(reinterpret_cast(m_queue), milliseconds); + assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + + bool ret = (res == WAIT_OBJECT_0); + + unsigned was_waiting=0; + unsigned was_gone=0; + + res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + was_waiting = m_waiting; + was_gone = m_gone; + if (was_waiting != 0) { - unsigned signals = 0; - - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); - - if (_waiting != 0) // the _gate is already closed + if (!ret) // timeout { - if (_blocked == 0) - { - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - return; - } - - ++_waiting; - --_blocked = 0; - } - else - { - res = WaitForSingleObject(reinterpret_cast(_gate), INFINITE); - assert(res == WAIT_OBJECT_0); - if (_blocked > _gone) - { - if (_gone != 0) - { - _blocked -= _gone; - _gone = 0; - } - signals = _waiting = 1; - --_blocked; - } + if (m_blocked != 0) + --m_blocked; else + ++m_gone; // count spurious wakeups + } + if (--m_waiting == 0) + { + if (m_blocked != 0) { - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); - assert(res); - } - - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - - if (signals) - { - res = ReleaseSemaphore(reinterpret_cast(_queue), signals, 0); + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); // open m_gate assert(res); + was_waiting = 0; } + else if (m_gone != 0) + m_gone = 0; } } - - void condition::notify_all() + else if (++m_gone == (std::numeric_limits::max() / 2)) { - unsigned signals = 0; - - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); + // timeout occured, normalize the m_gone count + // this may occur if many calls to wait with a timeout are made and + // no call to notify_* is made + res = WaitForSingleObject(reinterpret_cast(m_gate), INFINITE); assert(res == WAIT_OBJECT_0); - - if (_waiting != 0) // the _gate is already closed - { - if (_blocked == 0) - { - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - return; - } - - _waiting += (signals = _blocked); - _blocked = 0; - } - else - { - res = WaitForSingleObject(reinterpret_cast(_gate), INFINITE); - assert(res == WAIT_OBJECT_0); - if (_blocked > _gone) - { - if (_gone != 0) - { - _blocked -= _gone; - _gone = 0; - } - signals = _waiting = _blocked; - _blocked = 0; - } - else - { - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); - assert(res); - } - - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - - if (signals) - { - res = ReleaseSemaphore(reinterpret_cast(_queue), signals, 0); - assert(res); - } - } + m_blocked -= m_gone; + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); + assert(res); + m_gone = 0; } + res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); - void condition::enter_wait() + if (was_waiting == 1) { - int res = WaitForSingleObject(reinterpret_cast(_gate), INFINITE); - assert(res == WAIT_OBJECT_0); - ++_blocked; - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); + for (/**/ ; was_gone; --was_gone) + { + // better now than spurious later + res = WaitForSingleObject(reinterpret_cast(m_queue), INFINITE); + assert(res == WAIT_OBJECT_0); + } + res = ReleaseSemaphore(reinterpret_cast(m_gate), 1, 0); assert(res); } - void condition::do_wait() - { - int res = WaitForSingleObject(reinterpret_cast(_queue), INFINITE); - assert(res == WAIT_OBJECT_0); - - unsigned was_waiting=0; - unsigned was_gone=0; - - res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); - was_waiting = _waiting; - was_gone = _gone; - if (was_waiting != 0) - { - if (--_waiting == 0) - { - if (_blocked != 0) - { - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); // open _gate - assert(res); - was_waiting = 0; - } - else if (_gone != 0) - _gone = 0; - } - } - else if (++_gone == (std::numeric_limits::max() / 2)) - { - // timeout occured, normalize the _gone count - // this may occur if many calls to wait with a timeout are made and - // no call to notify_* is made - res = WaitForSingleObject(reinterpret_cast(_gate), INFINITE); - assert(res == WAIT_OBJECT_0); - _blocked -= _gone; - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); - assert(res); - _gone = 0; - } - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - - if (was_waiting == 1) - { - for (/**/ ; was_gone; --was_gone) - { - // better now than spurious later - res = WaitForSingleObject(reinterpret_cast(_queue), INFINITE); - assert(res == WAIT_OBJECT_0); - } - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); - assert(res); - } - } - - bool condition::do_timed_wait(const xtime& xt) - { - unsigned milliseconds; - to_duration(xt, milliseconds); - - int res = WaitForSingleObject(reinterpret_cast(_queue), milliseconds); - assert(res != WAIT_FAILED && res != WAIT_ABANDONED); - - bool ret = (res == WAIT_OBJECT_0); - - unsigned was_waiting=0; - unsigned was_gone=0; - - res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); - was_waiting = _waiting; - was_gone = _gone; - if (was_waiting != 0) - { - if (!ret) // timeout - { - if (_blocked != 0) - --_blocked; - else - ++_gone; // count spurious wakeups - } - if (--_waiting == 0) - { - if (_blocked != 0) - { - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); // open _gate - assert(res); - was_waiting = 0; - } - else if (_gone != 0) - _gone = 0; - } - } - else if (++_gone == (std::numeric_limits::max() / 2)) - { - // timeout occured, normalize the _gone count - // this may occur if many calls to wait with a timeout are made and - // no call to notify_* is made - res = WaitForSingleObject(reinterpret_cast(_gate), INFINITE); - assert(res == WAIT_OBJECT_0); - _blocked -= _gone; - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); - assert(res); - _gone = 0; - } - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - - if (was_waiting == 1) - { - for (/**/ ; was_gone; --was_gone) - { - // better now than spurious later - res = WaitForSingleObject(reinterpret_cast(_queue), INFINITE); - assert(res == WAIT_OBJECT_0); - } - res = ReleaseSemaphore(reinterpret_cast(_gate), 1, 0); - assert(res); - } - - return ret; - } + return ret; +} #elif defined(BOOST_HAS_PTHREADS) - condition::condition() - { - int res = pthread_cond_init(&_cond, 0); - assert(res == 0); +condition::condition() +{ + int res = pthread_cond_init(&m_condition, 0); + assert(res == 0); - if (res != 0) - throw std::runtime_error("boost::condition : failure to construct"); - } - - condition::~condition() - { - int res = pthread_cond_destroy(&_cond); - assert(res == 0); - } + if (res != 0) + throw std::runtime_error("boost::condition : failure to construct"); +} - void condition::notify_one() - { - int res = pthread_cond_signal(&_cond); - assert(res == 0); - } +condition::~condition() +{ + int res = pthread_cond_destroy(&m_condition); + assert(res == 0); +} - void condition::notify_all() - { - int res = pthread_cond_broadcast(&_cond); - assert(res == 0); - } +void condition::notify_one() +{ + int res = pthread_cond_signal(&m_condition); + assert(res == 0); +} - void condition::do_wait(pthread_mutex_t* pmutex) - { - int res = pthread_cond_wait(&_cond, pmutex); - assert(res == 0); - } +void condition::notify_all() +{ + int res = pthread_cond_broadcast(&m_condition); + assert(res == 0); +} - bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex) - { - timespec ts; - to_timespec(xt, ts); +void condition::do_wait(pthread_mutex_t* pmutex) +{ + int res = pthread_cond_wait(&m_condition, pmutex); + assert(res == 0); +} - int res = pthread_cond_timedwait(&_cond, pmutex, &ts); - assert(res == 0 || res == ETIMEDOUT); +bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex) +{ + timespec ts; + to_timespec(xt, ts); - return res != ETIMEDOUT; - } + int res = pthread_cond_timedwait(&m_condition, pmutex, &ts); + assert(res == 0 || res == ETIMEDOUT); + + return res != ETIMEDOUT; +} #endif + } // namespace boost + +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. +// 22 May 01 WEKEMPF Modified to use xtime for time outs. diff --git a/src/mutex.cpp b/src/mutex.cpp index a8eca5f8..ee627072 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -1,24 +1,19 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - */ +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. -#include -#include #include -#include +#include +#include #include +#include #include #include "timeconv.inl" @@ -29,371 +24,365 @@ # include #endif -/* - * Hack around various namespace challenged compilers - */ -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std { - using ::clock_t; - using ::clock; -} // namespace std -#endif +namespace boost { -namespace boost -{ #if defined(BOOST_HAS_WINTHREADS) - mutex::mutex() - { - _mutex = reinterpret_cast(CreateMutex(0, 0, 0)); - assert(_mutex); +mutex::mutex() +{ + m_mutex = reinterpret_cast(CreateMutex(0, 0, 0)); + assert(m_mutex); - if (!_mutex) - throw std::runtime_error("boost::mutex : failure to construct"); - } + if (!m_mutex) + throw std::runtime_error("boost::mutex : failure to construct"); +} - mutex::~mutex() - { - int res = CloseHandle(reinterpret_cast(_mutex)); - assert(res); - } - - void mutex::do_lock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); - } - - void mutex::do_unlock() - { - int res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - - void mutex::do_lock(cv_state& state) - { - do_lock(); - } - - void mutex::do_unlock(cv_state& state) - { - do_unlock(); - } +mutex::~mutex() +{ + int res = CloseHandle(reinterpret_cast(m_mutex)); + assert(res); +} - try_mutex::try_mutex() - { - _mutex = reinterpret_cast(CreateMutex(0, 0, 0)); - assert(_mutex); +void mutex::do_lock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); +} - if (!_mutex) - throw std::runtime_error("boost::try_mutex : failure to construct"); - } +void mutex::do_unlock() +{ + int res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); +} - try_mutex::~try_mutex() - { - int res = CloseHandle(reinterpret_cast(_mutex)); - assert(res); - } - - void try_mutex::do_lock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); - } - - bool try_mutex::do_trylock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), 0); - assert(res != WAIT_FAILED && res != WAIT_ABANDONED); - return res == WAIT_OBJECT_0; - } - - void try_mutex::do_unlock() - { - int res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - - void try_mutex::do_lock(cv_state& state) - { - do_lock(); - } - - void try_mutex::do_unlock(cv_state& state) - { - do_unlock(); - } +void mutex::do_lock(cv_state& state) +{ + do_lock(); +} - timed_mutex::timed_mutex() - { - _mutex = reinterpret_cast(CreateMutex(0, 0, 0)); - assert(_mutex); +void mutex::do_unlock(cv_state& state) +{ + do_unlock(); +} - if (!_mutex) - throw std::runtime_error("boost::timed_mutex : failure to construct"); - } +try_mutex::try_mutex() +{ + m_mutex = reinterpret_cast(CreateMutex(0, 0, 0)); + assert(m_mutex); - timed_mutex::~timed_mutex() - { - int res = CloseHandle(reinterpret_cast(_mutex)); - assert(res); - } - - void timed_mutex::do_lock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); - } - - bool timed_mutex::do_trylock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), 0); - assert(res != WAIT_FAILED && res != WAIT_ABANDONED); - return res == WAIT_OBJECT_0; - } - - bool timed_mutex::do_timedlock(const xtime& xt) - { - unsigned milliseconds; - to_duration(xt, milliseconds); + if (!m_mutex) + throw std::runtime_error("boost::try_mutex : failure to construct"); +} - int res = WaitForSingleObject(reinterpret_cast(_mutex), milliseconds); - assert(res != WAIT_FAILED && res != WAIT_ABANDONED); - return res == WAIT_OBJECT_0; - } - - void timed_mutex::do_unlock() - { - int res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - - void timed_mutex::do_lock(cv_state& state) - { - do_lock(); - } - - void timed_mutex::do_unlock(cv_state& state) - { - do_unlock(); - } +try_mutex::~try_mutex() +{ + int res = CloseHandle(reinterpret_cast(m_mutex)); + assert(res); +} + +void try_mutex::do_lock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); +} + +bool try_mutex::do_trylock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), 0); + assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + return res == WAIT_OBJECT_0; +} + +void try_mutex::do_unlock() +{ + int res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); +} + +void try_mutex::do_lock(cv_state& state) +{ + do_lock(); +} + +void try_mutex::do_unlock(cv_state& state) +{ + do_unlock(); +} + +timed_mutex::timed_mutex() +{ + m_mutex = reinterpret_cast(CreateMutex(0, 0, 0)); + assert(m_mutex); + + if (!m_mutex) + throw std::runtime_error("boost::timed_mutex : failure to construct"); +} + +timed_mutex::~timed_mutex() +{ + int res = CloseHandle(reinterpret_cast(m_mutex)); + assert(res); +} + +void timed_mutex::do_lock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); +} + +bool timed_mutex::do_trylock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), 0); + assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + return res == WAIT_OBJECT_0; +} + +bool timed_mutex::do_timedlock(const xtime& xt) +{ + unsigned milliseconds; + to_duration(xt, milliseconds); + + int res = WaitForSingleObject(reinterpret_cast(m_mutex), milliseconds); + assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + return res == WAIT_OBJECT_0; +} + +void timed_mutex::do_unlock() +{ + int res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); +} + +void timed_mutex::do_lock(cv_state& state) +{ + do_lock(); +} + +void timed_mutex::do_unlock(cv_state& state) +{ + do_unlock(); +} #elif defined(BOOST_HAS_PTHREADS) - mutex::mutex() - { - int res = pthread_mutex_init(&_mutex, 0); - assert(res == 0); +mutex::mutex() +{ + int res = pthread_mutex_init(&m_mutex, 0); + assert(res == 0); - if (res != 0) - throw std::runtime_error("boost::mutex : failure to construct"); + if (res != 0) + throw std::runtime_error("boost::mutex : failure to construct"); +} + +mutex::~mutex() +{ + int res = pthread_mutex_destroy(&m_mutex); + assert(res == 0); +} + +void mutex::do_lock() +{ + int res = pthread_mutex_lock(&m_mutex); + if (res == EDEADLK) throw lock_error(); + assert(res == 0); +} + +void mutex::do_unlock() +{ + int res = pthread_mutex_unlock(&m_mutex); + if (res == EPERM) throw lock_error(); + assert(res == 0); +} + +void mutex::do_lock(cv_state& state) +{ +} + +void mutex::do_unlock(cv_state& state) +{ + state.pmutex = &m_mutex; +} + +try_mutex::try_mutex() +{ + int res = pthread_mutex_init(&m_mutex, 0); + assert(res == 0); + + if (res != 0) + throw std::runtime_error("boost::try_mutex : failure to construct"); +} + +try_mutex::~try_mutex() +{ + int res = pthread_mutex_destroy(&m_mutex); + assert(res == 0); +} + +void try_mutex::do_lock() +{ + int res = pthread_mutex_lock(&m_mutex); + if (res == EDEADLK) throw lock_error(); + assert(res == 0); +} + +bool try_mutex::do_trylock() +{ + int res = pthread_mutex_trylock(&m_mutex); + if (res == EDEADLK) throw lock_error(); + assert(res == 0 || res == EBUSY); + return res == 0; +} + +void try_mutex::do_unlock() +{ + int res = pthread_mutex_unlock(&m_mutex); + if (res == EPERM) throw lock_error(); + assert(res == 0); +} + +void try_mutex::do_lock(cv_state& state) +{ +} + +void try_mutex::do_unlock(cv_state& state) +{ + state.pmutex = &m_mutex; +} + +timed_mutex::timed_mutex() + : m_locked(false) +{ + int res = pthread_mutex_init(&m_mutex, 0); + assert(res == 0); + + if (res != 0) + throw std::runtime_error("boost::timed_mutex : failure to construct"); + + res = pthread_cond_init(&m_condition, 0); + assert(res == 0); + + if (res != 0) + throw std::runtime_error("boost::timed_mutex : failure to construct"); +} + +timed_mutex::~timed_mutex() +{ + assert(!m_locked); + int res = pthread_mutex_destroy(&m_mutex); + assert(res == 0); + + res = pthread_cond_destroy(&m_condition); + assert(res == 0); +} + +void timed_mutex::do_lock() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + while (m_locked) + { + res = pthread_cond_wait(&m_condition, &m_mutex); + assert(res == 0); + } + + assert(!m_locked); + m_locked = true; + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +} + +bool timed_mutex::do_trylock() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + bool ret = false; + if (!m_locked) + { + m_locked = true; + ret = true; + } + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + return ret; +} + +bool timed_mutex::do_timedlock(const xtime& xt) +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + timespec ts; + to_timespec(xt, ts); + + while (m_locked) + { + res = pthread_cond_timedwait(&m_condition, &m_mutex, &ts); + assert(res == 0 || res == ETIMEDOUT); + + if (res == ETIMEDOUT) + break; } - mutex::~mutex() + bool ret = false; + if (!m_locked) { - int res = pthread_mutex_destroy(&_mutex); - assert(res == 0); - } - - void mutex::do_lock() - { - int res = pthread_mutex_lock(&_mutex); - if (res == EDEADLK) throw lock_error(); - assert(res == 0); - } - - void mutex::do_unlock() - { - int res = pthread_mutex_unlock(&_mutex); - if (res == EPERM) throw lock_error(); - assert(res == 0); - } - - void mutex::do_lock(cv_state& state) - { - } - - void mutex::do_unlock(cv_state& state) - { - state.pmutex = &_mutex; + m_locked = true; + ret = true; } - try_mutex::try_mutex() - { - int res = pthread_mutex_init(&_mutex, 0); - assert(res == 0); + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + return ret; +} - if (res != 0) - throw std::runtime_error("boost::try_mutex : failure to construct"); - } - - try_mutex::~try_mutex() +void timed_mutex::do_unlock() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + assert(m_locked); + m_locked = false; + + res = pthread_cond_signal(&m_condition); + assert(res == 0); + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +} + +void timed_mutex::do_lock(cv_state& state) +{ + int res; + while (m_locked) { - int res = pthread_mutex_destroy(&_mutex); - assert(res == 0); - } - - void try_mutex::do_lock() - { - int res = pthread_mutex_lock(&_mutex); - if (res == EDEADLK) throw lock_error(); + res = pthread_cond_wait(&m_condition, &m_mutex); assert(res == 0); } - bool try_mutex::do_trylock() - { - int res = pthread_mutex_trylock(&_mutex); - if (res == EDEADLK) throw lock_error(); - assert(res == 0 || res == EBUSY); - return res == 0; - } - - void try_mutex::do_unlock() - { - int res = pthread_mutex_unlock(&_mutex); - if (res == EPERM) throw lock_error(); - assert(res == 0); - } - - void try_mutex::do_lock(cv_state& state) - { - } - - void try_mutex::do_unlock(cv_state& state) - { - state.pmutex = &_mutex; - } + assert(!m_locked); + m_locked = true; - timed_mutex::timed_mutex() - : _locked(false) - { - int res = pthread_mutex_init(&_mutex, 0); - assert(res == 0); + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +} - if (res != 0) - throw std::runtime_error("boost::timed_mutex : failure to construct"); +void timed_mutex::do_unlock(cv_state& state) +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); - res = pthread_cond_init(&_cond, 0); - assert(res == 0); + assert(m_locked); + m_locked = false; - if (res != 0) - throw std::runtime_error("boost::timed_mutex : failure to construct"); - } + res = pthread_cond_signal(&m_condition); + assert(res == 0); - timed_mutex::~timed_mutex() - { - assert(!_locked); - int res = pthread_mutex_destroy(&_mutex); - assert(res == 0); - - res = pthread_cond_destroy(&_cond); - assert(res == 0); - } - - void timed_mutex::do_lock() - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - while (_locked) - { - res = pthread_cond_wait(&_cond, &_mutex); - assert(res == 0); - } - - assert(!_locked); - _locked = true; - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - } - - bool timed_mutex::do_trylock() - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - bool ret = false; - if (!_locked) - { - _locked = true; - ret = true; - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - return ret; - } - - bool timed_mutex::do_timedlock(const xtime& xt) - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - timespec ts; - to_timespec(xt, ts); - - while (_locked) - { - res = pthread_cond_timedwait(&_cond, &_mutex, &ts); - assert(res == 0 || res == ETIMEDOUT); - - if (res == ETIMEDOUT) - break; - } - - bool ret = false; - if (!_locked) - { - _locked = true; - ret = true; - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - return ret; - } - - void timed_mutex::do_unlock() - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - assert(_locked); - _locked = false; - - res = pthread_cond_signal(&_cond); - assert(res == 0); - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - } - - void timed_mutex::do_lock(cv_state& state) - { - int res; - while (_locked) - { - res = pthread_cond_wait(&_cond, &_mutex); - assert(res == 0); - } - - assert(!_locked); - _locked = true; - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - } - - void timed_mutex::do_unlock(cv_state& state) - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - assert(_locked); - _locked = false; - - res = pthread_cond_signal(&_cond); - assert(res == 0); - - state.pmutex = &_mutex; - } + state.pmutex = &m_mutex; +} #endif + } // namespace boost + +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. diff --git a/src/recursive_mutex.cpp b/src/recursive_mutex.cpp index 6e15f47d..d4268cce 100644 --- a/src/recursive_mutex.cpp +++ b/src/recursive_mutex.cpp @@ -1,24 +1,19 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - */ +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +#include #include #include -#include -#include #include +#include #include #include "timeconv.inl" @@ -29,741 +24,736 @@ # include #endif -/* - * Hack around various namespace challenged compilers - */ -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std { - using ::clock_t; - using ::clock; -} // namespace std -#endif - namespace boost { + #if defined(BOOST_HAS_WINTHREADS) - recursive_mutex::recursive_mutex() - : _count(0) - { - _mutex = reinterpret_cast(CreateMutex(0, 0, 0)); - assert(_mutex); +recursive_mutex::recursive_mutex() + : m_count(0) +{ + m_mutex = reinterpret_cast(CreateMutex(0, 0, 0)); + assert(m_mutex); - if (!_mutex) - throw std::runtime_error("boost::recursive_mutex : failure to construct"); - } + if (!m_mutex) + throw std::runtime_error("boost::recursive_mutex : failure to construct"); +} - recursive_mutex::~recursive_mutex() +recursive_mutex::~recursive_mutex() +{ + int res = CloseHandle(reinterpret_cast(m_mutex)); + assert(res); +} + +void recursive_mutex::do_lock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + + if (++m_count > 1) { - int res = CloseHandle(reinterpret_cast(_mutex)); + res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } - - void recursive_mutex::do_lock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); +} - if (++_count > 1) - { - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - } - - void recursive_mutex::do_unlock() +void recursive_mutex::do_unlock() +{ + if (--m_count == 0) { - if (--_count == 0) - { - int res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - } - - void recursive_mutex::do_lock(cv_state& state) - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); - - _count = state; - } - - void recursive_mutex::do_unlock(cv_state& state) - { - state = _count; - _count = 0; - - int res = ReleaseMutex(reinterpret_cast(_mutex)); + int res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } +} - recursive_try_mutex::recursive_try_mutex() - : _count(0) - { - _mutex = reinterpret_cast(CreateMutex(0, 0, 0)); - assert(_mutex); +void recursive_mutex::do_lock(cv_state& state) +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); - if (!_mutex) - throw std::runtime_error("boost::recursive_try_mutex : failure to construct"); - } - - recursive_try_mutex::~recursive_try_mutex() + m_count = state; +} + +void recursive_mutex::do_unlock(cv_state& state) +{ + state = m_count; + m_count = 0; + + int res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); +} + +recursive_try_mutex::recursive_try_mutex() + : m_count(0) +{ + m_mutex = reinterpret_cast(CreateMutex(0, 0, 0)); + assert(m_mutex); + + if (!m_mutex) + throw std::runtime_error("boost::recursive_try_mutex : failure to construct"); +} + +recursive_try_mutex::~recursive_try_mutex() +{ + int res = CloseHandle(reinterpret_cast(m_mutex)); + assert(res); +} + +void recursive_try_mutex::do_lock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + + if (++m_count > 1) { - int res = CloseHandle(reinterpret_cast(_mutex)); + res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } - - void recursive_try_mutex::do_lock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); +} - if (++_count > 1) +bool recursive_try_mutex::do_trylock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), 0); + assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + + if (res == WAIT_OBJECT_0) + { + if (+++m_count > 1) { - res = ReleaseMutex(reinterpret_cast(_mutex)); + res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } + return true; } - - bool recursive_try_mutex::do_trylock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), 0); - assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + return false; +} - if (res == WAIT_OBJECT_0) - { - if (+++_count > 1) - { - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - return true; - } - return false; - } - - void recursive_try_mutex::do_unlock() +void recursive_try_mutex::do_unlock() +{ + if (--m_count == 0) { - if (--_count == 0) - { - int res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - } - - void recursive_try_mutex::do_lock(cv_state& state) - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); - - _count = state; - } - - void recursive_try_mutex::do_unlock(cv_state& state) - { - state = _count; - _count = 0; - - int res = ReleaseMutex(reinterpret_cast(_mutex)); + int res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } +} - recursive_timed_mutex::recursive_timed_mutex() - : _count(0) +void recursive_try_mutex::do_lock(cv_state& state) +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + + m_count = state; +} + +void recursive_try_mutex::do_unlock(cv_state& state) +{ + state = m_count; + m_count = 0; + + int res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); +} + +recursive_timed_mutex::recursive_timed_mutex() + : m_count(0) +{ + m_mutex = reinterpret_cast(CreateMutex(0, 0, 0)); + assert(m_mutex); + + if (!m_mutex) + throw std::runtime_error("boost::recursive_timed_mutex : failure to construct"); +} + +recursive_timed_mutex::~recursive_timed_mutex() +{ + int res = CloseHandle(reinterpret_cast(m_mutex)); + assert(res); +} + +void recursive_timed_mutex::do_lock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + + if (++m_count > 1) { - _mutex = reinterpret_cast(CreateMutex(0, 0, 0)); - assert(_mutex); - - if (!_mutex) - throw std::runtime_error("boost::recursive_timed_mutex : failure to construct"); - } - - recursive_timed_mutex::~recursive_timed_mutex() - { - int res = CloseHandle(reinterpret_cast(_mutex)); + int res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } - - void recursive_timed_mutex::do_lock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); +} - if (++_count > 1) +bool recursive_timed_mutex::do_trylock() +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), 0); + assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + + if (res == WAIT_OBJECT_0) + { + if (+++m_count > 1) { - int res = ReleaseMutex(reinterpret_cast(_mutex)); + res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } + return true; } - - bool recursive_timed_mutex::do_trylock() - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), 0); - assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + return false; +} - if (res == WAIT_OBJECT_0) - { - if (+++_count > 1) - { - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - return true; - } - return false; - } - - bool recursive_timed_mutex::do_timedlock(const xtime& xt) - { - unsigned milliseconds; - to_duration(xt, milliseconds); +bool recursive_timed_mutex::do_timedlock(const xtime& xt) +{ + unsigned milliseconds; + to_duration(xt, milliseconds); - int res = WaitForSingleObject(reinterpret_cast(_mutex), milliseconds); - assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + int res = WaitForSingleObject(reinterpret_cast(m_mutex), milliseconds); + assert(res != WAIT_FAILED && res != WAIT_ABANDONED); - if (res == WAIT_OBJECT_0) - { - if (+++_count > 1) - { - res = ReleaseMutex(reinterpret_cast(_mutex)); - assert(res); - } - return true; - } - return false; - } - - void recursive_timed_mutex::do_unlock() + if (res == WAIT_OBJECT_0) { - if (--_count == 0) + if (+++m_count > 1) { - int res = ReleaseMutex(reinterpret_cast(_mutex)); + res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } + return true; } - - void recursive_timed_mutex::do_lock(cv_state& state) - { - int res = WaitForSingleObject(reinterpret_cast(_mutex), INFINITE); - assert(res == WAIT_OBJECT_0); + return false; +} - _count = state; - } - - void recursive_timed_mutex::do_unlock(cv_state& state) +void recursive_timed_mutex::do_unlock() +{ + if (--m_count == 0) { - state = _count; - _count = 0; - - int res = ReleaseMutex(reinterpret_cast(_mutex)); + int res = ReleaseMutex(reinterpret_cast(m_mutex)); assert(res); } +} + +void recursive_timed_mutex::do_lock(cv_state& state) +{ + int res = WaitForSingleObject(reinterpret_cast(m_mutex), INFINITE); + assert(res == WAIT_OBJECT_0); + + m_count = state; +} + +void recursive_timed_mutex::do_unlock(cv_state& state) +{ + state = m_count; + m_count = 0; + + int res = ReleaseMutex(reinterpret_cast(m_mutex)); + assert(res); +} #elif defined(BOOST_HAS_PTHREADS) - recursive_mutex::recursive_mutex() - : _count(0) +recursive_mutex::recursive_mutex() + : m_count(0) # if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - , _valid_id(false) + , m_valid_id(false) # endif - { - pthread_mutexattr_t attr; - int res = pthread_mutexattr_init(&attr); - assert(res == 0); +{ + pthread_mutexattr_t attr; + int res = pthread_mutexattr_init(&attr); + assert(res == 0); # if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - assert(res == 0); + res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + assert(res == 0); # endif - res = pthread_mutex_init(&_mutex, &attr); - assert(res == 0); + res = pthread_mutex_init(&m_mutex, &attr); + assert(res == 0); - if (res != 0) - throw std::runtime_error("boost::recursive_mutex : failure to construct"); + if (res != 0) + throw std::runtime_error("boost::recursive_mutex : failure to construct"); # if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - res = pthread_cond_init(&_unlocked, 0); - assert(res == 0); + res = pthread_cond_init(&m_unlocked, 0); + assert(res == 0); - if (res != 0) - throw std::runtime_error("boost::recursive_mutex : failure to construct"); + if (res != 0) + throw std::runtime_error("boost::recursive_mutex : failure to construct"); # endif - } +} - recursive_mutex::~recursive_mutex() - { - int res = pthread_mutex_destroy(&_mutex); - assert(res == 0); +recursive_mutex::~recursive_mutex() +{ + int res = pthread_mutex_destroy(&m_mutex); + assert(res == 0); # if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - res = pthread_cond_destroy(&_unlocked); - assert(res == 0); + res = pthread_cond_destroy(&m_unlocked); + assert(res == 0); # endif - } - - void recursive_mutex::do_lock() - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); +} + +void recursive_mutex::do_lock() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); # if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - if (++_count > 1) - { - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - } + if (++m_count > 1) + { + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + } # else - pthread_t tid = pthread_self(); - if (_valid_id && pthread_equal(_thread_id, tid)) - ++_count; - else - { - while (_valid_id) - { - res = pthread_cond_wait(&_unlocked, &_mutex); - assert(res == 0); - } - - _thread_id = tid; - _valid_id = true; - _count = 1; - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); -# endif - } - - void recursive_mutex::do_unlock() + pthread_t tid = pthread_self(); + if (m_valid_id && pthread_equal(m_thread_id, tid)) + ++m_count; + else { -# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - if (--_count == 0) + while (m_valid_id) { - int res = pthread_mutex_unlock(&_mutex); + res = pthread_cond_wait(&m_unlocked, &m_mutex); assert(res == 0); } + + m_thread_id = tid; + m_valid_id = true; + m_count = 1; + } + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +# endif +} + +void recursive_mutex::do_unlock() +{ +# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) + if (--m_count == 0) + { + int res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + } # else - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); - pthread_t tid = pthread_self(); - if (_valid_id && !pthread_equal(_thread_id, tid)) - { - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - throw lock_error(); - } - - if (--_count == 0) - { - assert(_valid_id); - _valid_id = false; - - res = pthread_cond_signal(&_unlocked); - assert(res == 0); - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); -# endif - } - - void recursive_mutex::do_lock(cv_state& state) + pthread_t tid = pthread_self(); + if (m_valid_id && !pthread_equal(m_thread_id, tid)) { + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + throw lock_error(); + } + + if (--m_count == 0) + { + assert(m_valid_id); + m_valid_id = false; + + res = pthread_cond_signal(&m_unlocked); + assert(res == 0); + } + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +# endif +} + +void recursive_mutex::do_lock(cv_state& state) +{ # if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - _count = state.count; + m_count = state.count; # else - int res; + int res; - while (_valid_id) - { - res = pthread_cond_wait(&_unlocked, &_mutex); - assert(res == 0); - } - - _thread_id = pthread_self(); - _valid_id = true; - _count = state.count; - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); -# endif - } - - void recursive_mutex::do_unlock(cv_state& state) + while (m_valid_id) { -# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - int res = pthread_mutex_lock(&_mutex); + res = pthread_cond_wait(&m_unlocked, &m_mutex); assert(res == 0); - - assert(_valid_id); - _valid_id = false; - - res = pthread_cond_signal(&_unlocked); - assert(res == 0); -# endif - - state.pmutex = &_mutex; - state.count = _count; } - recursive_try_mutex::recursive_try_mutex() - : _count(0) -# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - , _valid_id(false) + m_thread_id = pthread_self(); + m_valid_id = true; + m_count = state.count; + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); # endif - { - pthread_mutexattr_t attr; - int res = pthread_mutexattr_init(&attr); - assert(res == 0); +} + +void recursive_mutex::do_unlock(cv_state& state) +{ +# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + assert(m_valid_id); + m_valid_id = false; + + res = pthread_cond_signal(&m_unlocked); + assert(res == 0); +# endif + + state.pmutex = &m_mutex; + state.count = m_count; +} + +recursive_try_mutex::recursive_try_mutex() + : m_count(0) +# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) + , m_valid_id(false) +# endif +{ + pthread_mutexattr_t attr; + int res = pthread_mutexattr_init(&attr); + assert(res == 0); # if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - assert(res == 0); + res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + assert(res == 0); # endif - res = pthread_mutex_init(&_mutex, &attr); - assert(res == 0); + res = pthread_mutex_init(&m_mutex, &attr); + assert(res == 0); - if (res != 0) - throw std::runtime_error("boost::recursive_try_mutex : failure to construct"); + if (res != 0) + throw std::runtime_error("boost::recursive_try_mutex : failure to construct"); # if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - res = pthread_cond_init(&_unlocked, 0); - assert(res == 0); + res = pthread_cond_init(&m_unlocked, 0); + assert(res == 0); - if (res != 0) - throw std::runtime_error("boost::recursive_try_mutex : failure to construct"); + if (res != 0) + throw std::runtime_error("boost::recursive_try_mutex : failure to construct"); # endif - } +} - recursive_try_mutex::~recursive_try_mutex() - { - int res = pthread_mutex_destroy(&_mutex); - assert(res == 0); +recursive_try_mutex::~recursive_try_mutex() +{ + int res = pthread_mutex_destroy(&m_mutex); + assert(res == 0); # if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - res = pthread_cond_destroy(&_unlocked); - assert(res == 0); + res = pthread_cond_destroy(&m_unlocked); + assert(res == 0); # endif - } - - void recursive_try_mutex::do_lock() - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); +} + +void recursive_try_mutex::do_lock() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); # if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - if (++_count > 1) + if (++m_count > 1) + { + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + } +# else + pthread_t tid = pthread_self(); + if (m_valid_id && pthread_equal(m_thread_id, tid)) + ++m_count; + else + { + while (m_valid_id) { - res = pthread_mutex_unlock(&_mutex); + res = pthread_cond_wait(&m_unlocked, &m_mutex); assert(res == 0); } -# else - pthread_t tid = pthread_self(); - if (_valid_id && pthread_equal(_thread_id, tid)) - ++_count; - else - { - while (_valid_id) - { - res = pthread_cond_wait(&_unlocked, &_mutex); - assert(res == 0); - } - _thread_id = tid; - _valid_id = true; - _count = 1; - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); -# endif + m_thread_id = tid; + m_valid_id = true; + m_count = 1; } - - bool recursive_try_mutex::do_trylock() - { + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +# endif +} + +bool recursive_try_mutex::do_trylock() +{ # if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - int res = pthread_mutex_trylock(&_mutex); - assert(res == 0); + int res = pthread_mutex_trylock(&m_mutex); + assert(res == 0); - if (res == 0) - { - if (++_count > 1) - { - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - } - return true; - } - - return false; -# else - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - bool ret = false; - pthread_t tid = pthread_self(); - if (_valid_id && pthread_equal(_thread_id, tid)) - { - ++_count; - ret = true; - } - else if (!_valid_id) - { - _thread_id = tid; - _valid_id = true; - _count = 1; - ret = true; - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - return ret; -# endif - } - - void recursive_try_mutex::do_unlock() + if (res == 0) { + if (++m_count > 1) + { + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + } + return true; + } + + return false; +# else + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + bool ret = false; + pthread_t tid = pthread_self(); + if (m_valid_id && pthread_equal(m_thread_id, tid)) + { + ++m_count; + ret = true; + } + else if (!m_valid_id) + { + m_thread_id = tid; + m_valid_id = true; + m_count = 1; + ret = true; + } + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + return ret; +# endif +} + +void recursive_try_mutex::do_unlock() +{ # if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - if (--_count == 0) - { - int res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - } -# else - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - pthread_t tid = pthread_self(); - if (_valid_id && !pthread_equal(_thread_id, tid)) - { - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - throw lock_error(); - } - - if (--_count == 0) - { - assert(_valid_id); - _valid_id = false; - - res = pthread_cond_signal(&_unlocked); - assert(res == 0); - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); -# endif - } - - void recursive_try_mutex::do_lock(cv_state& state) + if (--m_count == 0) { + int res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + } +# else + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + pthread_t tid = pthread_self(); + if (m_valid_id && !pthread_equal(m_thread_id, tid)) + { + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + throw lock_error(); + } + + if (--m_count == 0) + { + assert(m_valid_id); + m_valid_id = false; + + res = pthread_cond_signal(&m_unlocked); + assert(res == 0); + } + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +# endif +} + +void recursive_try_mutex::do_lock(cv_state& state) +{ # if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - _count = state.count; + m_count = state.count; # else - int res; + int res; - while (_valid_id) - { - res = pthread_cond_wait(&_unlocked, &_mutex); - assert(res == 0); - } - - _thread_id = pthread_self(); - _valid_id = true; - _count = state.count; - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); -# endif - } - - void recursive_try_mutex::do_unlock(cv_state& state) + while (m_valid_id) { + res = pthread_cond_wait(&m_unlocked, &m_mutex); + assert(res == 0); + } + + m_thread_id = pthread_self(); + m_valid_id = true; + m_count = state.count; + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +# endif +} + +void recursive_try_mutex::do_unlock(cv_state& state) +{ # if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); - assert(_valid_id); - _valid_id = false; + assert(m_valid_id); + m_valid_id = false; - res = pthread_cond_signal(&_unlocked); - assert(res == 0); + res = pthread_cond_signal(&m_unlocked); + assert(res == 0); # endif - state.pmutex = &_mutex; - state.count = _count; + state.pmutex = &m_mutex; + state.count = m_count; +} + +recursive_timed_mutex::recursive_timed_mutex() + : m_valid_id(false), m_count(0) +{ + int res = pthread_mutex_init(&m_mutex, 0); + assert(res == 0); + + if (res != 0) + throw std::runtime_error("boost::recursive_timed_mutex : failure to construct"); + + res = pthread_cond_init(&m_unlocked, 0); + assert(res == 0); + + if (res != 0) + throw std::runtime_error("boost::recursive_timed_mutex : failure to construct"); +} + +recursive_timed_mutex::~recursive_timed_mutex() +{ + int res = pthread_mutex_destroy(&m_mutex); + assert(res == 0); + + res = pthread_cond_destroy(&m_unlocked); + assert(res == 0); +} + +void recursive_timed_mutex::do_lock() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + pthread_t tid = pthread_self(); + if (m_valid_id && pthread_equal(m_thread_id, tid)) + ++m_count; + else + { + while (m_valid_id) + { + res = pthread_cond_wait(&m_unlocked, &m_mutex); + assert(res == 0); + } + + m_thread_id = tid; + m_valid_id = true; + m_count = 1; } - recursive_timed_mutex::recursive_timed_mutex() - : _valid_id(false), _count(0) - { - int res = pthread_mutex_init(&_mutex, 0); - assert(res == 0); + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +} - if (res != 0) - throw std::runtime_error("boost::recursive_timed_mutex : failure to construct"); +bool recursive_timed_mutex::do_trylock() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + bool ret = false; + pthread_t tid = pthread_self(); + if (m_valid_id && pthread_equal(m_thread_id, tid)) + { + ++m_count; + ret = true; + } + else if (!m_valid_id) + { + m_thread_id = tid; + m_valid_id = true; + m_count = 1; + ret = true; + } + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + return ret; +} + +bool recursive_timed_mutex::do_timedlock(const xtime& xt) +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + bool ret = false; + pthread_t tid = pthread_self(); + if (m_valid_id && pthread_equal(m_thread_id, tid)) + { + ++m_count; + ret = true; + } + else + { + timespec ts; + to_timespec(xt, ts); + + while (m_valid_id) + { + res = pthread_cond_timedwait(&m_unlocked, &m_mutex, &ts); + if (res == ETIMEDOUT) + break; + assert(res == 0); + } - res = pthread_cond_init(&_unlocked, 0); - assert(res == 0); - - if (res != 0) - throw std::runtime_error("boost::recursive_timed_mutex : failure to construct"); - } - - recursive_timed_mutex::~recursive_timed_mutex() - { - int res = pthread_mutex_destroy(&_mutex); - assert(res == 0); - - res = pthread_cond_destroy(&_unlocked); - assert(res == 0); - } - - void recursive_timed_mutex::do_lock() - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - pthread_t tid = pthread_self(); - if (_valid_id && pthread_equal(_thread_id, tid)) - ++_count; - else + if (!m_valid_id) { - while (_valid_id) - { - res = pthread_cond_wait(&_unlocked, &_mutex); - assert(res == 0); - } - - _thread_id = tid; - _valid_id = true; - _count = 1; - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - } - - bool recursive_timed_mutex::do_trylock() - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - bool ret = false; - pthread_t tid = pthread_self(); - if (_valid_id && pthread_equal(_thread_id, tid)) - { - ++_count; + m_thread_id = tid; + m_valid_id = true; + m_count = 1; ret = true; } - else if (!_valid_id) - { - _thread_id = tid; - _valid_id = true; - _count = 1; - ret = true; - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - return ret; } - - bool recursive_timed_mutex::do_timedlock(const xtime& xt) + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + return ret; +} + +void recursive_timed_mutex::do_unlock() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + pthread_t tid = pthread_self(); + if (m_valid_id && !pthread_equal(m_thread_id, tid)) { - int res = pthread_mutex_lock(&_mutex); + res = pthread_mutex_unlock(&m_mutex); assert(res == 0); - - bool ret = false; - pthread_t tid = pthread_self(); - if (_valid_id && pthread_equal(_thread_id, tid)) - { - ++_count; - ret = true; - } - else - { - timespec ts; - to_timespec(xt, ts); - - while (_valid_id) - { - res = pthread_cond_timedwait(&_unlocked, &_mutex, &ts); - if (res == ETIMEDOUT) - break; - assert(res == 0); - } - - if (!_valid_id) - { - _thread_id = tid; - _valid_id = true; - _count = 1; - ret = true; - } - } - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - return ret; + throw lock_error(); } - - void recursive_timed_mutex::do_unlock() + + if (--m_count == 0) { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); + assert(m_valid_id); + m_valid_id = false; - pthread_t tid = pthread_self(); - if (_valid_id && !pthread_equal(_thread_id, tid)) - { - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - throw lock_error(); - } - - if (--_count == 0) - { - assert(_valid_id); - _valid_id = false; - - res = pthread_cond_signal(&_unlocked); - assert(res == 0); - } - - res = pthread_mutex_unlock(&_mutex); + res = pthread_cond_signal(&m_unlocked); assert(res == 0); } - - void recursive_timed_mutex::do_lock(cv_state& state) + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +} + +void recursive_timed_mutex::do_lock(cv_state& state) +{ + int res; + + while (m_valid_id) { - int res; - - while (_valid_id) - { - res = pthread_cond_wait(&_unlocked, &_mutex); - assert(res == 0); - } - - _thread_id = pthread_self(); - _valid_id = true; - _count = state.count; - - res = pthread_mutex_unlock(&_mutex); + res = pthread_cond_wait(&m_unlocked, &m_mutex); assert(res == 0); } - - void recursive_timed_mutex::do_unlock(cv_state& state) - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - assert(_valid_id); - _valid_id = false; + m_thread_id = pthread_self(); + m_valid_id = true; + m_count = state.count; - res = pthread_cond_signal(&_unlocked); - assert(res == 0); + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +} - state.pmutex = &_mutex; - state.count = _count; - } +void recursive_timed_mutex::do_unlock(cv_state& state) +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + assert(m_valid_id); + m_valid_id = false; + + res = pthread_cond_signal(&m_unlocked); + assert(res == 0); + + state.pmutex = &m_mutex; + state.count = m_count; +} #endif + } // namespace boost + +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. diff --git a/src/semaphore.cpp b/src/semaphore.cpp index 3d9173e4..4e7de6ea 100644 --- a/src/semaphore.cpp +++ b/src/semaphore.cpp @@ -1,25 +1,19 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 22 May 01 Modified to use xtime for time outs. - */ - +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + #include -#include -#include -#include +#include #include +#include +#include #include "timeconv.inl" #if defined(BOOST_HAS_WINTHREADS) @@ -30,154 +24,150 @@ # include #endif -/* - * Hack around various namespace challenged compilers - */ -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std { - using ::clock_t; - using ::clock; -} // namespace std -#endif - namespace boost { + #if defined(BOOST_HAS_WINTHREADS) - semaphore::semaphore(unsigned count, unsigned max) - { - if (static_cast(max) <= 0) - max = std::numeric_limits::max(); +semaphore::semaphore(unsigned count, unsigned max) +{ + if (static_cast(max) <= 0) + max = std::numeric_limits::max(); - _sema = reinterpret_cast(CreateSemaphore(0, count, max, 0)); - assert(_sema != 0); + m_sema = reinterpret_cast(CreateSemaphore(0, count, max, 0)); + assert(m_sema != 0); - if (!_sema) - throw std::runtime_error("boost::semaphore : failure to construct"); - } - - semaphore::~semaphore() - { - int res = CloseHandle(reinterpret_cast(_sema)); - assert(res); - } - - bool semaphore::up(unsigned count, unsigned* prev) - { - long p; - bool ret = !!ReleaseSemaphore(reinterpret_cast(_sema), count, &p); - assert(ret || GetLastError() == ERROR_TOO_MANY_POSTS); + if (!m_sema) + throw std::runtime_error("boost::semaphore : failure to construct"); +} - if (prev) - *prev = p; +semaphore::~semaphore() +{ + int res = CloseHandle(reinterpret_cast(m_sema)); + assert(res); +} - return ret; - } - - void semaphore::down() - { - int res = WaitForSingleObject(reinterpret_cast(_sema), INFINITE); - assert(res == WAIT_OBJECT_0); - } +bool semaphore::up(unsigned count, unsigned* prev) +{ + long p; + bool ret = !!ReleaseSemaphore(reinterpret_cast(m_sema), count, &p); + assert(ret || GetLastError() == ERROR_TOO_MANY_POSTS); - bool semaphore::down(const xtime& xt) - { - unsigned milliseconds; - to_duration(xt, milliseconds); - int res = WaitForSingleObject(reinterpret_cast(_sema), milliseconds); - assert(res != WAIT_FAILED && res != WAIT_ABANDONED); - return res == WAIT_OBJECT_0; - } + if (prev) + *prev = p; + + return ret; +} + +void semaphore::down() +{ + int res = WaitForSingleObject(reinterpret_cast(m_sema), INFINITE); + assert(res == WAIT_OBJECT_0); +} + +bool semaphore::down(const xtime& xt) +{ + unsigned milliseconds; + to_duration(xt, milliseconds); + int res = WaitForSingleObject(reinterpret_cast(m_sema), milliseconds); + assert(res != WAIT_FAILED && res != WAIT_ABANDONED); + return res == WAIT_OBJECT_0; +} #elif defined(BOOST_HAS_PTHREADS) - semaphore::semaphore(unsigned count, unsigned max) - : _available(count), _max(max ? max : std::numeric_limits::max()) +semaphore::semaphore(unsigned count, unsigned max) + : m_available(count), m_max(max ? max : std::numeric_limits::max()) +{ + int res = pthread_mutex_init(&m_mutex, 0); + assert(res == 0); + + if (res != 0) + throw std::runtime_error("boost::semaphore : failure to construct"); + + res = pthread_cond_init(&m_condition, 0); + assert(res == 0); + + if (res != 0) + throw std::runtime_error("boost::semaphore : failure to construct"); +} + +semaphore::~semaphore() +{ + int res = pthread_mutex_destroy(&m_mutex); + assert(res == 0); + + res = pthread_cond_destroy(&m_condition); + assert(res == 0); +} + +bool semaphore::up(unsigned count, unsigned* prev) +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + if (prev) + *prev = m_available; + + if (m_available + count > m_max) { - int res = pthread_mutex_init(&_mutex, 0); + res = pthread_mutex_unlock(&m_mutex); assert(res == 0); - - if (res != 0) - throw std::runtime_error("boost::semaphore : failure to construct"); - - res = pthread_cond_init(&_cond, 0); - assert(res == 0); - - if (res != 0) - throw std::runtime_error("boost::semaphore : failure to construct"); + return false; } - semaphore::~semaphore() - { - int res = pthread_mutex_destroy(&_mutex); - assert(res == 0); + m_available += count; - res = pthread_cond_destroy(&_cond); + res = pthread_cond_broadcast(&m_condition); + assert(res == 0); + + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + return true; +} + +void semaphore::down() +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + while (m_available == 0) + { + res = pthread_cond_wait(&m_condition, &m_mutex); assert(res == 0); } - - bool semaphore::up(unsigned count, unsigned* prev) - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - if (prev) - *prev = _available; - - if (_available + count > _max) + m_available--; + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); +} + +bool semaphore::down(const xtime& xt) +{ + int res = pthread_mutex_lock(&m_mutex); + assert(res == 0); + + timespec ts; + to_timespec(xt, ts); + + while (m_available == 0) + { + res = pthread_cond_timedwait(&m_condition, &m_mutex, &ts); + assert(res == 0 || res == ETIMEDOUT); + + if (res == ETIMEDOUT) { - res = pthread_mutex_unlock(&_mutex); + res = pthread_mutex_unlock(&m_mutex); assert(res == 0); return false; } - - _available += count; - - res = pthread_cond_broadcast(&_cond); - assert(res == 0); - - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - return true; } - void semaphore::down() - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - while (_available == 0) - { - res = pthread_cond_wait(&_cond, &_mutex); - assert(res == 0); - } - - _available--; - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - } - - bool semaphore::down(const xtime& xt) - { - int res = pthread_mutex_lock(&_mutex); - assert(res == 0); - - timespec ts; - to_timespec(xt, ts); - - while (_available == 0) - { - res = pthread_cond_timedwait(&_cond, &_mutex, &ts); - assert(res == 0 || res == ETIMEDOUT); - - if (res == ETIMEDOUT) - { - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - return false; - } - } - - _available--; - res = pthread_mutex_unlock(&_mutex); - assert(res == 0); - return true; - } + m_available--; + res = pthread_mutex_unlock(&m_mutex); + assert(res == 0); + return true; +} #endif + } // namespace boost + +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. +// 22 May 01 WEKEMPF Modified to use xtime for time outs. diff --git a/src/thread.cpp b/src/thread.cpp index 7172d6fa..ffc80d44 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -1,23 +1,17 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - * 1 Jun 01 Added boost::thread initial implementation. - * 3 Jul 01 Redesigned boost::thread to be noncopyable. - */ - +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + #include #include +#include #include #if defined(BOOST_HAS_WINTHREADS) @@ -28,331 +22,339 @@ #include "timeconv.inl" #if defined(BOOST_HAS_PTHREADS) -namespace boost +namespace boost { + +// This class is used to signal thread objects when the thread dies. +class thread::thread_list { - // This class is used to signal thread objects when the thread dies. - class thread::thread_list +public: + thread_list() { } + ~thread_list() { - public: - thread_list() { } - ~thread_list() + mutex::lock lock(m_mutex); + for (std::list::iterator it = m_thread_objects.begin(); it != m_thread_objects.end(); ++it) { - mutex::lock lock(m_mutex); - for (std::list::iterator it = m_list.begin(); it != m_list.end(); ++it) - { - mutex::lock lock((*it)->m_mutex); - (*it)->m_list = 0; - (*it)->m_cond.notify_all(); - } + mutex::lock lock((*it)->m_mutex); + (*it)->m_state_manager = 0; + (*it)->m_condition.notify_all(); } + } - void add(thread* thrd) - { - mutex::lock lock(m_mutex); - m_list.push_back(thrd); - } + void add(thread* thrd) + { + mutex::lock lock(m_mutex); + m_thread_objects.push_back(thrd); + } - void remove(thread* thrd) - { - mutex::lock lock(m_mutex); - std::list::iterator it = std::find(m_list.begin(), m_list.end(), thrd); - if (it != m_list.end()) - m_list.erase(it); - } + void remove(thread* thrd) + { + mutex::lock lock(m_mutex); + std::list::iterator it = std::find(m_thread_objects.begin(), m_thread_objects.end(), thrd); + if (it != m_thread_objects.end()) + m_thread_objects.erase(it); + } - private: - std::list m_list; - mutex m_mutex; - }; +private: + std::list m_thread_objects; + mutex m_mutex; +}; + +} // namespace boost +#endif + +namespace { + +#if defined(BOOST_HAS_PTHREADS) +pthread_key_t key; +pthread_once_t once = PTHREAD_ONCE_INIT; + +void destroy_list(void* p) +{ + boost::thread::thread_list* list = static_cast(p); + delete list; +} + +void init_key() +{ + int res = pthread_key_create(&key, &destroy_list); + assert(res == 0); +} + +pthread_key_t get_key() +{ + int res = pthread_once(&once, &init_key); + assert(res == 0); + return key; +} + +boost::thread::thread_list* get_list() +{ + pthread_key_t key = get_key(); + boost::thread::thread_list* list = static_cast(pthread_getspecific(key)); + if (!list) + { + list = new boost::thread::thread_list; + pthread_setspecific(key, list); + } + return list; } #endif -namespace +class thread_param { +public: + thread_param(const boost::function0& threadfunc) : m_threadfunc(threadfunc), m_started(false) { } + void wait() + { + boost::mutex::lock lock(m_mutex); + while (!m_started) + m_condition.wait(lock); + } + void started() + { + boost::mutex::lock lock(m_mutex); + m_started = true; + m_condition.notify_one(); + } + + boost::mutex m_mutex; + boost::condition m_condition; + const boost::function0& m_threadfunc; + bool m_started; #if defined(BOOST_HAS_PTHREADS) - pthread_key_t key; - pthread_once_t once = PTHREAD_ONCE_INIT; - - void destroy_list(void* p) - { - boost::thread::thread_list* list = static_cast(p); - delete list; - } - - void init_key() - { - int res = pthread_key_create(&key, &destroy_list); - assert(res == 0); - } - - pthread_key_t get_key() - { - int res = pthread_once(&once, &init_key); - assert(res == 0); - return key; - } - - boost::thread::thread_list* get_list() - { - pthread_key_t key = get_key(); - boost::thread::thread_list* list = static_cast(pthread_getspecific(key)); - if (!list) - { - list = new boost::thread::thread_list; - pthread_setspecific(key, list); - } - return list; - } + boost::thread::thread_list* m_state_manager; #endif - - class thread_param - { - public: - thread_param(const boost::function0& threadfunc) : m_threadfunc(threadfunc), m_started(false) { } - void wait() - { - boost::mutex::lock lock(m_mutex); - while (!m_started) - m_cond.wait(lock); - } - void started() - { - boost::mutex::lock lock(m_mutex); - m_started = true; - m_cond.notify_one(); - } - - boost::mutex m_mutex; - boost::condition m_cond; - const boost::function0& m_threadfunc; - bool m_started; -#if defined(BOOST_HAS_PTHREADS) - boost::thread::thread_list* m_list; -#endif - }; +}; #if defined(BOOST_HAS_WINTHREADS) - unsigned __stdcall thread_proxy(void* param) +unsigned __stdcall thread_proxy(void* param) #elif defined(BOOST_HAS_PTHREADS) - void* thread_proxy(void* param) +void* thread_proxy(void* param) #endif - { - thread_param* p = static_cast(param); - boost::function0 threadfunc = p->m_threadfunc; +{ + thread_param* p = static_cast(param); + boost::function0 threadfunc = p->m_threadfunc; #if defined(BOOST_HAS_PTHREADS) - p->m_list = get_list(); // create the list + p->m_state_manager = get_list(); // create the list #endif - p->started(); - threadfunc(); - return 0; - } + p->started(); + threadfunc(); + return 0; } -namespace boost +} // unnamed namespace + +namespace boost { + +lock_error::lock_error() : std::runtime_error("thread lock error") { - lock_error::lock_error() : std::runtime_error("thread lock error") - { - } +} - thread::thread() - { +thread::thread() +{ #if defined(BOOST_HAS_WINTHREADS) - HANDLE cur = GetCurrentThread(); - HANDLE real; - DuplicateHandle(GetCurrentProcess(), cur, GetCurrentProcess(), &real, 0, FALSE, DUPLICATE_SAME_ACCESS); - m_thread = reinterpret_cast(real); - m_id = GetCurrentThreadId(); + HANDLE cur = GetCurrentThread(); + HANDLE real; + DuplicateHandle(GetCurrentProcess(), cur, GetCurrentProcess(), &real, 0, FALSE, DUPLICATE_SAME_ACCESS); + m_thread = reinterpret_cast(real); + m_id = GetCurrentThreadId(); #elif defined(BOOST_HAS_PTHREADS) - m_thread = pthread_self(); - m_list = get_list(); - m_list->add(this); + m_thread = pthread_self(); + m_state_manager = get_list(); + m_state_manager->add(this); #endif - } - - thread::thread(const boost::function0& threadfunc) - { - thread_param param(threadfunc); +} + +thread::thread(const function0& threadfunc) +{ + thread_param param(threadfunc); #if defined(BOOST_HAS_WINTHREADS) - m_thread = _beginthreadex(0, 0, &thread_proxy, ¶m, 0, &m_id); - assert(m_thread); + m_thread = _beginthreadex(0, 0, &thread_proxy, ¶m, 0, &m_id); + assert(m_thread); #elif defined(BOOST_HAS_PTHREADS) - int res = pthread_create(&m_thread, 0, &thread_proxy, ¶m); - assert(res == 0); + int res = pthread_create(&m_thread, 0, &thread_proxy, ¶m); + assert(res == 0); #endif - param.wait(); + param.wait(); #if defined(BOOST_HAS_PTHREADS) - m_list = param.m_list; - assert(m_list); - m_list->add(this); + m_state_manager = param.m_state_manager; + assert(m_state_manager); + m_state_manager->add(this); #endif - } +} - thread::~thread() - { - int res = 0; +thread::~thread() +{ + int res = 0; #if defined(BOOST_HAS_WINTHREADS) - res = CloseHandle(reinterpret_cast(m_thread)); - assert(res); + res = CloseHandle(reinterpret_cast(m_thread)); + assert(res); #elif defined(BOOST_HAS_PTHREADS) - { - mutex::lock lock(m_mutex); - if (m_list) - m_list->remove(this); - } - - res = pthread_detach(m_thread); - assert(res == 0); -#endif - } - - bool thread::operator==(const thread& other) { -#if defined(BOOST_HAS_WINTHREADS) - return other.m_id == m_id; -#elif defined(BOOST_HAS_PTHREADS) - return pthread_equal(m_thread, other.m_thread) != 0; -#endif - } - - bool thread::operator!=(const thread& other) - { - return operator!=(other); - } - - void thread::join() - { - int res; -#if defined(BOOST_HAS_WINTHREADS) - res = WaitForSingleObject(reinterpret_cast(m_thread), INFINITE); - assert(res == WAIT_OBJECT_0); -#elif defined(BOOST_HAS_PTHREADS) mutex::lock lock(m_mutex); - while (m_list) - m_cond.wait(lock); -#endif + if (m_state_manager) + m_state_manager->remove(this); } - bool thread::try_join() - { + res = pthread_detach(m_thread); + assert(res == 0); +#endif +} + +bool thread::operator==(const thread& other) const +{ #if defined(BOOST_HAS_WINTHREADS) - return WaitForSingleObject(reinterpret_cast(m_thread), 0) == WAIT_OBJECT_0; + return other.m_id == m_id; #elif defined(BOOST_HAS_PTHREADS) - mutex::lock lock(m_mutex); - bool ret = (m_list == 0); - return ret; + return pthread_equal(m_thread, other.m_thread) != 0; #endif - } +} - bool thread::timed_join(const xtime& xt) - { +bool thread::operator!=(const thread& other) const +{ + return operator!=(other); +} + +void thread::join() +{ + int res; #if defined(BOOST_HAS_WINTHREADS) - unsigned milliseconds; - to_duration(xt, milliseconds); - return WaitForSingleObject(reinterpret_cast(m_thread), 0) == WAIT_OBJECT_0; + res = WaitForSingleObject(reinterpret_cast(m_thread), INFINITE); + assert(res == WAIT_OBJECT_0); #elif defined(BOOST_HAS_PTHREADS) - mutex::lock lock(m_mutex); - while (m_list) - { - if (!m_cond.timed_wait(lock, xt)) - break; - } - bool ret = (m_list == 0); - return ret; + mutex::lock lock(m_mutex); + while (m_state_manager) + m_condition.wait(lock); #endif - } +} - void thread::sleep(const xtime& xt) - { +bool thread::try_join() +{ #if defined(BOOST_HAS_WINTHREADS) - unsigned milliseconds; - to_duration(xt, milliseconds); - Sleep(milliseconds); + return WaitForSingleObject(reinterpret_cast(m_thread), 0) == WAIT_OBJECT_0; +#elif defined(BOOST_HAS_PTHREADS) + mutex::lock lock(m_mutex); + bool ret = (m_state_manager == 0); + return ret; +#endif +} + +bool thread::timed_join(const xtime& xt) +{ +#if defined(BOOST_HAS_WINTHREADS) + unsigned milliseconds; + to_duration(xt, milliseconds); + return WaitForSingleObject(reinterpret_cast(m_thread), 0) == WAIT_OBJECT_0; +#elif defined(BOOST_HAS_PTHREADS) + mutex::lock lock(m_mutex); + while (m_state_manager) + { + if (!m_condition.timed_wait(lock, xt)) + break; + } + bool ret = (m_state_manager == 0); + return ret; +#endif +} + +void thread::sleep(const xtime& xt) +{ +#if defined(BOOST_HAS_WINTHREADS) + unsigned milliseconds; + to_duration(xt, milliseconds); + Sleep(milliseconds); #elif defined(BOOST_HAS_PTHREADS) # if defined(BOOST_HAS_PTHREAD_DELAY_NP) - timespec ts; - to_timespec(xt, ts); - int res = pthread_delay_np(&ts); - assert(res == 0); + timespec ts; + to_timespec(xt, ts); + int res = pthread_delay_np(&ts); + assert(res == 0); # elif defined(BOOST_HAS_NANOSLEEP) - timespec ts; - to_timespec(xt, ts); - nanosleep(&ts, 0); + timespec ts; + to_timespec(xt, ts); + nanosleep(&ts, 0); # else - boost::semaphore sema; - sema.down(xt); + semaphore sema; + sema.down(xt); # endif #endif - } +} - void thread::yield() - { +void thread::yield() +{ #if defined(BOOST_HAS_WINTHREADS) - Sleep(0); + Sleep(0); #elif defined(BOOST_HAS_PTHREADS) # if defined(BOOST_HAS_SCHED_YIELD) - int res = sched_yield(); - assert(res == 0); + int res = sched_yield(); + assert(res == 0); # elif defined(BOOST_HAS_PTHREAD_YIELD) - int res = pthread_yield(); - assert(res == 0); + int res = pthread_yield(); + assert(res == 0); # else - xtime xt; - xtime_get(&xt, boost::TIME_UTC); - sleep(xt); + xtime xt; + xtime_get(&xt, TIME_UTC); + sleep(xt); # endif #endif - } +} - thread_group::thread_group() - { - } +thread_group::thread_group() +{ +} - thread_group::~thread_group() - { - // We shouldn't have to lock here, since referencing this object from another thread - // while we're deleting it in the current thread is going to lead to undefined behavior - // any way. - for (std::list::iterator it = m_threads.begin(); it != m_threads.end(); ++it) - delete (*it); - } +thread_group::~thread_group() +{ + // We shouldn't have to lock here, since referencing this object from another thread + // while we're deleting it in the current thread is going to lead to undefined behavior + // any way. + for (std::list::iterator it = m_threads.begin(); it != m_threads.end(); ++it) + delete (*it); +} - thread* thread_group::create_thread(const function0& threadfunc) - { - // No lock required here since the only "shared data" that's modified here occurs - // inside add_thread which does lock. - std::auto_ptr thrd(new thread(threadfunc)); - add_thread(thrd.get()); - return thrd.release(); - } +thread* thread_group::create_thread(const function0& threadfunc) +{ + // No lock required here since the only "shared data" that's modified here occurs + // inside add_thread which does lock. + std::auto_ptr thrd(new thread(threadfunc)); + add_thread(thrd.get()); + return thrd.release(); +} - void thread_group::add_thread(thread* thrd) - { - mutex::lock lock(m_mutex); +void thread_group::add_thread(thread* thrd) +{ + mutex::lock lock(m_mutex); - // For now we'll simply ignore requests to add a thread object multiple times. - // Should we consider this an error and either throw or return an error value? - std::list::iterator it = std::find(m_threads.begin(), m_threads.end(), thrd); - assert(it == m_threads.end()); - if (it == m_threads.end()) - m_threads.push_back(thrd); - } + // For now we'll simply ignore requests to add a thread object multiple times. + // Should we consider this an error and either throw or return an error value? + std::list::iterator it = std::find(m_threads.begin(), m_threads.end(), thrd); + assert(it == m_threads.end()); + if (it == m_threads.end()) + m_threads.push_back(thrd); +} - void thread_group::remove_thread(thread* thrd) - { - mutex::lock lock(m_mutex); +void thread_group::remove_thread(thread* thrd) +{ + mutex::lock lock(m_mutex); - // For now we'll simply ignore requests to remove a thread object that's not in the group. - // Should we consider this an error and either throw or return an error value? - std::list::iterator it = std::find(m_threads.begin(), m_threads.end(), thrd); - assert(it != m_threads.end()); - if (it != m_threads.end()) - m_threads.erase(it); - } + // For now we'll simply ignore requests to remove a thread object that's not in the group. + // Should we consider this an error and either throw or return an error value? + std::list::iterator it = std::find(m_threads.begin(), m_threads.end(), thrd); + assert(it != m_threads.end()); + if (it != m_threads.end()) + m_threads.erase(it); +} - void thread_group::join_all() - { - mutex::lock lock(m_mutex); - for (std::list::iterator it = m_threads.begin(); it != m_threads.end(); ++it) - (*it)->join(); - } -} \ No newline at end of file +void thread_group::join_all() +{ + mutex::lock lock(m_mutex); + for (std::list::iterator it = m_threads.begin(); it != m_threads.end(); ++it) + (*it)->join(); +} + +} // namespace boost + +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. +// 1 Jun 01 WEKEMPF Added boost::thread initial implementation. +// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable. diff --git a/src/tss.cpp b/src/tss.cpp index 01f3cf37..8fcba723 100644 --- a/src/tss.cpp +++ b/src/tss.cpp @@ -1,79 +1,77 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 6 Jun 01 Initial version. - */ - +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + #include #include +#include #if defined(BOOST_HAS_WINTHREADS) # include #endif -#include +namespace boost { -namespace boost -{ #if defined(BOOST_HAS_WINTHREADS) - tss::tss() - { - _key = TlsAlloc(); - assert(_key != 0xFFFFFFFF); +tss::tss() +{ + m_key = TlsAlloc(); + assert(m_key != 0xFFFFFFFF); - if (_key == 0xFFFFFFFF) - throw std::runtime_error("boost::tss : failure to construct"); - } + if (m_key == 0xFFFFFFFF) + throw std::runtime_error("boost::tss : failure to construct"); +} - tss::~tss() - { - int res = TlsFree(_key); - assert(res); - } +tss::~tss() +{ + int res = TlsFree(m_key); + assert(res); +} - void* tss::get() const - { - return TlsGetValue(_key); - } +void* tss::get() const +{ + return TlsGetValue(m_key); +} - bool tss::set(void* value) - { - return TlsSetValue(_key, value); - } +bool tss::set(void* value) +{ + return TlsSetValue(m_key, value); +} #elif defined(BOOST_HAS_PTHREADS) - tss::tss() - { - int res = pthread_key_create(&_key, 0); - assert(res == 0); +tss::tss() +{ + int res = pthread_key_create(&m_key, 0); + assert(res == 0); - if (res != 0) - throw std::runtime_error("boost::tss : failure to construct"); - } + if (res != 0) + throw std::runtime_error("boost::tss : failure to construct"); +} - tss::~tss() - { - int res = pthread_key_delete(_key); - assert(res == 0); - } +tss::~tss() +{ + int res = pthread_key_delete(m_key); + assert(res == 0); +} - void* tss::get() const - { - return pthread_getspecific(_key); - } +void* tss::get() const +{ + return pthread_getspecific(m_key); +} - bool tss::set(void* value) - { - return pthread_setspecific(_key, value) == 0; - } +bool tss::set(void* value) +{ + return pthread_setspecific(m_key, value) == 0; +} #endif -} \ No newline at end of file + +} // namespace boost + +// Change Log: +// 6 Jun 01 WEKEMPF Initial version. diff --git a/src/xtime.cpp b/src/xtime.cpp index 23f31108..baeff44c 100644 --- a/src/xtime.cpp +++ b/src/xtime.cpp @@ -1,19 +1,14 @@ -/* - * Copyright (C) 2001 - * William E. Kempf - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. William E. Kempf makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * Revision History (excluding minor changes for specific compilers) - * 8 Feb 01 Initial version. - */ - +// Copyright (C) 2001 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + #include #include @@ -22,34 +17,39 @@ #endif namespace boost { - int xtime_get(struct xtime* xtp, int clock_type) + +int xtime_get(struct xtime* xtp, int clock_type) +{ + if (clock_type == TIME_UTC) { - if (clock_type == TIME_UTC) - { #if defined(BOOST_HAS_FTIME) - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - const __int64 TIMESPEC_TO_FILETIME_OFFSET = ((__int64)27111902 << 32) + (__int64)3577643008; - xtp->sec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000); - xtp->nsec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET - - ((__int64)xtp->sec * (__int64)10000000)) * 100); - return clock_type; + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + const __int64 TIMESPEC_TO_FILETIME_OFFSET = ((__int64)27111902 << 32) + (__int64)3577643008; + xtp->sec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000); + xtp->nsec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET - + ((__int64)xtp->sec * (__int64)10000000)) * 100); + return clock_type; #elif defined(BOOST_HAS_GETTIMEOFDAY) - struct timeval tv; - gettimeofday(&tv, 0); - xtp->sec = tv.tv_sec; - xtp->nsec = tv.tv_usec * 1000; - return clock_type; + struct timeval tv; + gettimeofday(&tv, 0); + xtp->sec = tv.tv_sec; + xtp->nsec = tv.tv_usec * 1000; + return clock_type; #elif defined(BOOST_HAS_CLOCK_GETTIME) - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - xtp->sec = ts.tv_sec; - xtp->nsec = ts.tv_nsec; - return clock_type; + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + xtp->sec = ts.tv_sec; + xtp->nsec = ts.tv_nsec; + return clock_type; #else - return 0; -#endif - } return 0; +#endif } -} \ No newline at end of file + return 0; +} + +} // namespace boost + +// Change Log: +// 8 Feb 01 WEKEMPF Initial version. diff --git a/test/test_thread.cpp b/test/test_thread.cpp index bc016632..af4bd35b 100644 --- a/test/test_thread.cpp +++ b/test/test_thread.cpp @@ -6,6 +6,7 @@ //#include #include #include +#include #define BOOST_INCLUDE_MAIN #include