sl@0: // Copyright (C) 2001-2003 sl@0: // William E. Kempf sl@0: // sl@0: // Distributed under the Boost Software License, Version 1.0. (See accompanying sl@0: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: #ifndef BOOST_CONDITION_WEK070601_HPP sl@0: #define BOOST_CONDITION_WEK070601_HPP sl@0: sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #if defined(BOOST_HAS_PTHREADS) sl@0: # include sl@0: #elif defined(BOOST_HAS_MPTASKS) sl@0: # include "scoped_critical_region.hpp" sl@0: #endif sl@0: sl@0: namespace boost { sl@0: sl@0: struct xtime; sl@0: // disable warnings about non dll import sl@0: // see: http://www.boost.org/more/separate_compilation.html#dlls sl@0: #ifdef BOOST_MSVC sl@0: # pragma warning(push) sl@0: # pragma warning(disable: 4251 4231 4660 4275) sl@0: #endif sl@0: sl@0: namespace detail { sl@0: sl@0: class BOOST_THREAD_DECL condition_impl : private noncopyable sl@0: { sl@0: friend class condition; sl@0: sl@0: public: sl@0: condition_impl(); sl@0: ~condition_impl(); sl@0: sl@0: void notify_one(); sl@0: void notify_all(); sl@0: sl@0: #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) sl@0: void enter_wait(); sl@0: void do_wait(); sl@0: bool do_timed_wait(const xtime& xt); sl@0: #elif defined(BOOST_HAS_PTHREADS) sl@0: void do_wait(pthread_mutex_t* pmutex); sl@0: bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex); sl@0: #endif sl@0: sl@0: #if defined(BOOST_HAS_WINTHREADS) sl@0: void* m_gate; sl@0: void* m_queue; sl@0: void* m_mutex; sl@0: unsigned m_gone; // # threads that timed out and never made it to m_queue sl@0: unsigned long m_blocked; // # threads blocked on the condition sl@0: unsigned m_waiting; // # threads no longer waiting for the condition but sl@0: // still waiting to be removed from m_queue sl@0: #elif defined(BOOST_HAS_PTHREADS) sl@0: pthread_cond_t m_condition; sl@0: #elif defined(BOOST_HAS_MPTASKS) sl@0: MPSemaphoreID m_gate; sl@0: MPSemaphoreID m_queue; sl@0: threads::mac::detail::scoped_critical_region m_mutex; sl@0: threads::mac::detail::scoped_critical_region m_mutex_mutex; sl@0: unsigned m_gone; // # threads that timed out and never made it to m_queue sl@0: unsigned long m_blocked; // # threads blocked on the condition sl@0: unsigned m_waiting; // # threads no longer waiting for the condition but sl@0: // still waiting to be removed from m_queue sl@0: #endif sl@0: }; sl@0: sl@0: } // namespace detail sl@0: sl@0: class condition : private noncopyable sl@0: { sl@0: public: sl@0: condition() { } sl@0: ~condition() { } sl@0: sl@0: void notify_one() { m_impl.notify_one(); } sl@0: void notify_all() { m_impl.notify_all(); } sl@0: sl@0: template sl@0: void wait(L& lock) sl@0: { sl@0: if (!lock) sl@0: throw lock_error(); sl@0: sl@0: do_wait(lock.m_mutex); sl@0: } sl@0: sl@0: template sl@0: void wait(L& lock, Pr pred) sl@0: { sl@0: if (!lock) sl@0: throw lock_error(); sl@0: sl@0: while (!pred()) sl@0: do_wait(lock.m_mutex); sl@0: } sl@0: sl@0: template sl@0: bool timed_wait(L& lock, const xtime& xt) sl@0: { sl@0: if (!lock) sl@0: throw lock_error(); sl@0: sl@0: return do_timed_wait(lock.m_mutex, xt); sl@0: } sl@0: sl@0: template sl@0: bool timed_wait(L& lock, const xtime& xt, Pr pred) sl@0: { sl@0: if (!lock) sl@0: throw lock_error(); sl@0: sl@0: while (!pred()) sl@0: { sl@0: if (!do_timed_wait(lock.m_mutex, xt)) sl@0: return false; sl@0: } sl@0: sl@0: return true; sl@0: } sl@0: sl@0: private: sl@0: detail::condition_impl m_impl; sl@0: sl@0: template sl@0: void do_wait(M& mutex) sl@0: { sl@0: #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) sl@0: m_impl.enter_wait(); sl@0: #endif sl@0: sl@0: typedef detail::thread::lock_ops sl@0: #if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG) sl@0: # define lock_ops lock_ops_ // HP confuses lock_ops witht the template sl@0: #endif sl@0: lock_ops; sl@0: sl@0: typename lock_ops::lock_state state; sl@0: lock_ops::unlock(mutex, state); sl@0: sl@0: #if defined(BOOST_HAS_PTHREADS) sl@0: m_impl.do_wait(state.pmutex); sl@0: #elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) sl@0: m_impl.do_wait(); sl@0: #endif sl@0: sl@0: lock_ops::lock(mutex, state); sl@0: #undef lock_ops sl@0: } sl@0: sl@0: template sl@0: bool do_timed_wait(M& mutex, const xtime& xt) sl@0: { sl@0: #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) sl@0: m_impl.enter_wait(); sl@0: #endif sl@0: sl@0: typedef detail::thread::lock_ops sl@0: #if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG) sl@0: # define lock_ops lock_ops_ // HP confuses lock_ops witht the template sl@0: #endif sl@0: lock_ops; sl@0: sl@0: typename lock_ops::lock_state state; sl@0: lock_ops::unlock(mutex, state); sl@0: sl@0: bool ret = false; sl@0: sl@0: #if defined(BOOST_HAS_PTHREADS) sl@0: ret = m_impl.do_timed_wait(xt, state.pmutex); sl@0: #elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) sl@0: ret = m_impl.do_timed_wait(xt); sl@0: #endif sl@0: sl@0: lock_ops::lock(mutex, state); sl@0: #undef lock_ops sl@0: sl@0: return ret; sl@0: } sl@0: }; sl@0: #ifdef BOOST_MSVC sl@0: # pragma warning(pop) sl@0: #endif sl@0: } // namespace boost sl@0: sl@0: // Change Log: sl@0: // 8 Feb 01 WEKEMPF Initial version. sl@0: // 22 May 01 WEKEMPF Modified to use xtime for time outs. sl@0: // 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too sl@0: // difficult to use with spurious wakeups. sl@0: // 3 Jan 03 WEKEMPF Modified for DLL implementation. sl@0: sl@0: #endif // BOOST_CONDITION_WEK070601_HPP