|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2007-10-19 13:40:05
Author: anthonyw
Date: 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
New Revision: 40191
URL: http://svn.boost.org/trac/boost/changeset/40191
Log:
New condition_variable and condition_variable_any as per proposed C++0x interface
Added:
trunk/boost/thread/condition_variable.hpp (contents, props changed)
trunk/boost/thread/pthread/condition_variable.hpp (contents, props changed)
trunk/boost/thread/win32/condition_variable.hpp (contents, props changed)
Removed:
trunk/libs/thread/src/barrier.cpp
trunk/libs/thread/src/condition.cpp
Text files modified:
trunk/boost/thread/barrier.hpp | 65 ++++++++-----
trunk/boost/thread/condition.hpp | 198 +--------------------------------------
trunk/boost/thread/exceptions.hpp | 12 ++
trunk/boost/thread/pthread/mutex.hpp | 7 +
trunk/boost/thread/pthread/shared_mutex.hpp | 7
trunk/boost/thread/thread.hpp | 1
trunk/boost/thread/win32/interlocked_read.hpp | 19 +++
trunk/boost/thread/xtime.hpp | 13 ++
trunk/libs/thread/build/Jamfile.v2 | 4
9 files changed, 102 insertions(+), 224 deletions(-)
Modified: trunk/boost/thread/barrier.hpp
==============================================================================
--- trunk/boost/thread/barrier.hpp (original)
+++ trunk/boost/thread/barrier.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -1,5 +1,6 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
+// Copyright (C) 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -11,33 +12,47 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
+#include <string>
+#include <stdexcept>
-namespace boost {
-
-class BOOST_THREAD_DECL barrier
+namespace boost
{
-public:
- barrier(unsigned int count);
- ~barrier();
-
- bool wait();
-
-private:
- mutex m_mutex;
-// disable warnings about non dll import
-// see: http://www.boost.org/more/separate_compilation.html#dlls
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4251 4231 4660 4275)
-#endif
- condition m_cond;
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
- unsigned int m_threshold;
- unsigned int m_count;
- unsigned int m_generation;
-};
+
+ class barrier
+ {
+ public:
+ barrier(unsigned int count)
+ : m_threshold(count), m_count(count), m_generation(0)
+ {
+ if (count == 0)
+ throw std::invalid_argument("count cannot be zero.");
+ }
+
+ bool wait()
+ {
+ boost::mutex::scoped_lock lock(m_mutex);
+ unsigned int gen = m_generation;
+
+ if (--m_count == 0)
+ {
+ m_generation++;
+ m_count = m_threshold;
+ m_cond.notify_all();
+ return true;
+ }
+
+ while (gen == m_generation)
+ m_cond.wait(lock);
+ return false;
+ }
+
+ private:
+ mutex m_mutex;
+ condition m_cond;
+ unsigned int m_threshold;
+ unsigned int m_count;
+ unsigned int m_generation;
+ };
} // namespace boost
Modified: trunk/boost/thread/condition.hpp
==============================================================================
--- trunk/boost/thread/condition.hpp (original)
+++ trunk/boost/thread/condition.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -1,196 +1,10 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-// Copyright (C) 2007 Anthony Williams
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_THREAD_CONDITION_HPP
+#define BOOST_THREAD_CONDITION_HPP
+#include <boost/thread/condition_variable.hpp>
-#ifndef BOOST_CONDITION_WEK070601_HPP
-#define BOOST_CONDITION_WEK070601_HPP
-
-#include <boost/thread/detail/config.hpp>
-
-#include <boost/thread/exceptions.hpp>
-#include <boost/utility.hpp>
-
-#if defined(BOOST_HAS_PTHREADS)
-# include <pthread.h>
-#elif defined(BOOST_HAS_MPTASKS)
-# include "scoped_critical_region.hpp"
-#endif
-
-namespace boost {
-
-struct xtime;
-// disable warnings about non dll import
-// see: http://www.boost.org/more/separate_compilation.html#dlls
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4251 4231 4660 4275)
-#endif
-
-namespace detail {
-
-class BOOST_THREAD_DECL condition_impl : private noncopyable
+namespace boost
{
- friend class condition;
-
-public:
- condition_impl();
- ~condition_impl();
-
- void notify_one();
- void notify_all();
-
-#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
- 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);
-#endif
-
-#if defined(BOOST_HAS_WINTHREADS)
- void* m_gate;
- void* m_queue;
- void* m_mutex;
- unsigned m_gone; // # threads that timed out and never made it to m_queue
- unsigned long m_blocked; // # threads blocked on the condition
- unsigned m_waiting; // # threads no longer waiting for the condition but
- // still waiting to be removed from m_queue
-#elif defined(BOOST_HAS_PTHREADS)
- pthread_cond_t m_condition;
- pthread_mutex_t m_mutex;
-#elif defined(BOOST_HAS_MPTASKS)
- MPSemaphoreID m_gate;
- MPSemaphoreID m_queue;
- threads::mac::detail::scoped_critical_region m_mutex;
- threads::mac::detail::scoped_critical_region m_mutex_mutex;
- unsigned m_gone; // # threads that timed out and never made it to m_queue
- unsigned long m_blocked; // # threads blocked on the condition
- unsigned m_waiting; // # threads no longer waiting for the condition but
- // still waiting to be removed from m_queue
-#endif
-};
-
-} // namespace detail
-
-class condition : private noncopyable
-{
-public:
- condition() { }
- ~condition() { }
-
- void notify_one() { m_impl.notify_one(); }
- void notify_all() { m_impl.notify_all(); }
-
- template <typename L>
- void wait(L& lock)
- {
- if (!lock)
- throw lock_error();
-
- do_wait(*lock.mutex());
- }
-
- template <typename L, typename Pr>
- void wait(L& lock, Pr pred)
- {
- if (!lock)
- throw lock_error();
-
- while (!pred())
- do_wait(*lock.mutex());
- }
+ typedef condition_variable_any condition;
+}
- template <typename L>
- bool timed_wait(L& lock, const xtime& xt)
- {
- if (!lock)
- throw lock_error();
-
- return do_timed_wait(*lock.mutex(), xt);
- }
-
- template <typename L, typename Pr>
- 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:
- detail::condition_impl m_impl;
-
- template <typename M>
- void do_wait(M& mutex)
- {
-#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
- m_impl.enter_wait();
-#else
- pthread_mutex_lock(&m_impl.m_mutex);
#endif
-
- mutex.unlock();
-
-#if defined(BOOST_HAS_PTHREADS)
- m_impl.do_wait(&m_impl.m_mutex);
-#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
- m_impl.do_wait();
-#endif
-
-#if defined(BOOST_HAS_PTHREADS)
- pthread_mutex_unlock(&m_impl.m_mutex);
-#endif
- mutex.lock();
- }
-
- template <typename M>
- bool do_timed_wait(M& mutex, const xtime& xt)
- {
-#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
- m_impl.enter_wait();
-#else
- pthread_mutex_lock(&m_impl.m_mutex);
-#endif
-
- mutex.unlock();
-
- bool ret = false;
-
-#if defined(BOOST_HAS_PTHREADS)
- ret = m_impl.do_timed_wait(xt, &m_impl.m_mutex);
-#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
- ret = m_impl.do_timed_wait(xt);
-#endif
-
-#if defined(BOOST_HAS_PTHREADS)
- pthread_mutex_unlock(&m_impl.m_mutex);
-#endif
- mutex.lock();
-
- return ret;
- }
-};
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
-} // namespace boost
-
-// Change Log:
-// 8 Feb 01 WEKEMPF Initial version.
-// 22 May 01 WEKEMPF Modified to use xtime for time outs.
-// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too
-// difficult to use with spurious wakeups.
-// 3 Jan 03 WEKEMPF Modified for DLL implementation.
-
-#endif // BOOST_CONDITION_WEK070601_HPP
Added: trunk/boost/thread/condition_variable.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/condition_variable.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -0,0 +1,15 @@
+#ifndef BOOST_THREAD_CONDITION_VARIABLE_HPP
+#define BOOST_THREAD_CONDITION_VARIABLE_HPP
+
+// condition_variable.hpp
+//
+// (C) Copyright 2007 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/thread/detail/platform.hpp>
+#include BOOST_THREAD_PLATFORM(condition_variable.hpp)
+
+#endif
Modified: trunk/boost/thread/exceptions.hpp
==============================================================================
--- trunk/boost/thread/exceptions.hpp (original)
+++ trunk/boost/thread/exceptions.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -1,5 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
+// Copyright (C) 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -35,6 +36,17 @@
int m_sys_err;
};
+ class condition_error:
+ public std::exception
+ {
+ public:
+ const char* what() const throw()
+ {
+ return "Condition error";
+ }
+ };
+
+
class BOOST_THREAD_DECL lock_error : public thread_exception
{
public:
Added: trunk/boost/thread/pthread/condition_variable.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/pthread/condition_variable.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -0,0 +1,194 @@
+#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
+#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// (C) Copyright 2007 Anthony Williams
+
+#include <boost/thread/mutex.hpp>
+#include <limits.h>
+#include <boost/assert.hpp>
+#include <algorithm>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <pthread.h>
+#include "timespec.hpp"
+#include "pthread_mutex_scoped_lock.hpp"
+
+namespace boost
+{
+ class condition_variable
+ {
+ private:
+ pthread_cond_t cond;
+
+ condition_variable(condition_variable&);
+ condition_variable& operator=(condition_variable&);
+ public:
+ condition_variable()
+ {
+ int const res=pthread_cond_init(&cond,NULL);
+ if(res)
+ {
+ throw thread_resource_error();
+ }
+ }
+ ~condition_variable()
+ {
+ int const res=pthread_cond_destroy(&cond);
+ BOOST_ASSERT(!res);
+ }
+
+ void wait(unique_lock<mutex>& m)
+ {
+ int const cond_res=pthread_cond_wait(&cond,m.mutex()->native_handle());
+ BOOST_ASSERT(!cond_res);
+ }
+
+ template<typename predicate_type>
+ void wait(unique_lock<mutex>& m,predicate_type pred)
+ {
+ while(!pred()) wait(m);
+ }
+
+ bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
+ {
+ struct timespec const timeout=detail::get_timespec(wait_until);
+ int const cond_res=pthread_cond_timedwait(&cond,m.mutex()->native_handle(),&timeout);
+ if(cond_res==ETIMEDOUT)
+ {
+ return false;
+ }
+ BOOST_ASSERT(!cond_res);
+ return true;
+ }
+
+ template<typename predicate_type>
+ bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
+ {
+ while (!pred())
+ {
+ if(!timed_wait(m, wait_until))
+ return false;
+ }
+ return true;
+ }
+
+ void notify_one()
+ {
+ int const res=pthread_cond_signal(&cond);
+ BOOST_ASSERT(!res);
+ }
+
+ void notify_all()
+ {
+ int const res=pthread_cond_broadcast(&cond);
+ BOOST_ASSERT(!res);
+ }
+ };
+
+ class condition_variable_any
+ {
+ pthread_mutex_t internal_mutex;
+ pthread_cond_t cond;
+
+ condition_variable_any(condition_variable&);
+ condition_variable_any& operator=(condition_variable&);
+
+ public:
+ condition_variable_any()
+ {
+ int const res=pthread_mutex_init(&internal_mutex,NULL);
+ if(res)
+ {
+ throw thread_resource_error();
+ }
+ int const res2=pthread_cond_init(&cond,NULL);
+ if(res2)
+ {
+ int const destroy_res=pthread_mutex_destroy(&internal_mutex);
+ BOOST_ASSERT(!destroy_res);
+ throw thread_resource_error();
+ }
+ }
+ ~condition_variable_any()
+ {
+ int const res=pthread_mutex_destroy(&internal_mutex);
+ BOOST_ASSERT(!res);
+ int const res2=pthread_cond_destroy(&cond);
+ BOOST_ASSERT(!res2);
+ }
+
+ template<typename lock_type>
+ void wait(lock_type& m)
+ {
+ int res=0;
+ {
+ boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+ m.unlock();
+ res=pthread_cond_wait(&cond,&internal_mutex);
+ }
+ m.lock();
+ if(res)
+ {
+ throw condition_error();
+ }
+ }
+
+ template<typename lock_type,typename predicate_type>
+ void wait(lock_type& m,predicate_type pred)
+ {
+ while(!pred()) wait(m);
+ }
+
+ template<typename lock_type>
+ bool timed_wait(lock_type& m,boost::system_time const& wait_until)
+ {
+ struct timespec const timeout=detail::get_timespec(wait_until);
+ int res=0;
+ {
+ boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+ m.unlock();
+ res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
+ }
+ m.lock();
+ if(res==ETIMEDOUT)
+ {
+ return false;
+ }
+ if(res)
+ {
+ throw condition_error();
+ }
+ return true;
+ }
+
+ template<typename lock_type,typename predicate_type>
+ bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
+ {
+ while (!pred())
+ {
+ if(!timed_wait(m, wait_until))
+ return false;
+ }
+ return true;
+ }
+
+ void notify_one()
+ {
+ boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+ int const res=pthread_cond_signal(&cond);
+ BOOST_ASSERT(!res);
+ }
+
+ void notify_all()
+ {
+ boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+ int const res=pthread_cond_broadcast(&cond);
+ BOOST_ASSERT(!res);
+ }
+ };
+
+}
+
+#endif
Modified: trunk/boost/thread/pthread/mutex.hpp
==============================================================================
--- trunk/boost/thread/pthread/mutex.hpp (original)
+++ trunk/boost/thread/pthread/mutex.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -62,6 +62,13 @@
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
+
+ typedef pthread_mutex_t* native_handle_type;
+ native_handle_type native_handle() const
+ {
+ return &m;
+ }
+
typedef unique_lock<mutex> scoped_lock;
typedef scoped_lock scoped_try_lock;
};
Modified: trunk/boost/thread/pthread/shared_mutex.hpp
==============================================================================
--- trunk/boost/thread/pthread/shared_mutex.hpp (original)
+++ trunk/boost/thread/pthread/shared_mutex.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -11,7 +11,6 @@
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
-#include <boost/thread/xtime.hpp>
namespace boost
{
@@ -95,7 +94,7 @@
return true;
}
- if(!shared_cond.timed_wait(lock,get_xtime(timeout)))
+ if(!shared_cond.timed_wait(lock,timeout))
{
return false;
}
@@ -157,7 +156,7 @@
state.exclusive=true;
return true;
}
- if(!exclusive_cond.timed_wait(lock,get_xtime(timeout)))
+ if(!exclusive_cond.timed_wait(lock,timeout))
{
return false;
}
@@ -216,7 +215,7 @@
return true;
}
- if(!shared_cond.timed_wait(lock,get_xtime(timeout)))
+ if(!shared_cond.timed_wait(lock,timeout))
{
return false;
}
Modified: trunk/boost/thread/thread.hpp
==============================================================================
--- trunk/boost/thread/thread.hpp (original)
+++ trunk/boost/thread/thread.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -17,7 +17,6 @@
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
-# include <boost/thread/condition.hpp>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif
Added: trunk/boost/thread/win32/condition_variable.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/win32/condition_variable.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -0,0 +1,309 @@
+#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
+#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// (C) Copyright 2007 Anthony Williams
+
+#include <boost/thread/mutex.hpp>
+#include "thread_primitives.hpp"
+#include <limits.h>
+#include <boost/assert.hpp>
+#include <algorithm>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/thread_time.hpp>
+#include "interlocked_read.hpp"
+
+namespace boost
+{
+ namespace detail
+ {
+ class basic_condition_variable
+ {
+ boost::mutex internal_mutex;
+ long total_count;
+ unsigned active_generation_count;
+
+ struct list_entry
+ {
+ detail::win32::handle semaphore;
+ long count;
+ bool notified;
+ };
+
+ BOOST_STATIC_CONSTANT(unsigned,generation_count=3);
+
+ list_entry generations[generation_count];
+ detail::win32::handle wake_sem;
+
+ static bool no_waiters(list_entry const& entry)
+ {
+ return entry.count==0;
+ }
+
+ void shift_generations_down()
+ {
+ list_entry* const last_active_entry=std::remove_if(generations,generations+generation_count,no_waiters);
+ if(last_active_entry==generations+generation_count)
+ {
+ broadcast_entry(generations[generation_count-1],false);
+ }
+ else
+ {
+ active_generation_count=(last_active_entry-generations)+1;
+ }
+
+ std::copy_backward(generations,generations+active_generation_count-1,generations+active_generation_count);
+ generations[0]=list_entry();
+ }
+
+ void broadcast_entry(list_entry& entry,bool wake)
+ {
+ long const count_to_wake=entry.count;
+ detail::interlocked_write_release(&total_count,total_count-count_to_wake);
+ if(wake)
+ {
+ detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
+ }
+ detail::win32::ReleaseSemaphore(entry.semaphore,count_to_wake,0);
+ entry.count=0;
+ dispose_entry(entry);
+ }
+
+
+ void dispose_entry(list_entry& entry)
+ {
+ if(entry.semaphore)
+ {
+ unsigned long const close_result=detail::win32::CloseHandle(entry.semaphore);
+ BOOST_ASSERT(close_result);
+ entry.semaphore=0;
+ }
+ entry.notified=false;
+ }
+
+ template<typename lock_type>
+ struct relocker
+ {
+ lock_type& lock;
+ bool unlocked;
+
+ relocker(lock_type& lock_):
+ lock(lock_),unlocked(false)
+ {}
+ void unlock()
+ {
+ lock.unlock();
+ unlocked=true;
+ }
+ ~relocker()
+ {
+ if(unlocked)
+ {
+ lock.lock();
+ }
+
+ }
+ };
+
+
+ protected:
+ template<typename lock_type>
+ bool do_wait(lock_type& lock,::boost::system_time const& wait_until)
+ {
+ detail::win32::handle_manager local_wake_sem;
+ detail::win32::handle_manager sem;
+ bool first_loop=true;
+ bool woken=false;
+
+ relocker<lock_type> locker(lock);
+
+ while(!woken)
+ {
+ {
+ boost::mutex::scoped_lock internal_lock(internal_mutex);
+ detail::interlocked_write_release(&total_count,total_count+1);
+ if(first_loop)
+ {
+ locker.unlock();
+ if(!wake_sem)
+ {
+ wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
+ BOOST_ASSERT(wake_sem);
+ }
+ local_wake_sem=detail::win32::duplicate_handle(wake_sem);
+
+ if(generations[0].notified)
+ {
+ shift_generations_down();
+ }
+ else if(!active_generation_count)
+ {
+ active_generation_count=1;
+ }
+
+ first_loop=false;
+ }
+ if(!generations[0].semaphore)
+ {
+ generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
+ BOOST_ASSERT(generations[0].semaphore);
+ }
+ ++generations[0].count;
+ sem=detail::win32::duplicate_handle(generations[0].semaphore);
+ }
+ unsigned long const wait_result=detail::win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until));
+
+ if(wait_result==detail::win32::timeout)
+ {
+ break;
+ }
+ BOOST_ASSERT(!wait_result);
+
+ unsigned long const woken_result=detail::win32::WaitForSingleObject(local_wake_sem,0);
+ BOOST_ASSERT(woken_result==detail::win32::timeout || woken_result==0);
+
+ woken=(woken_result==0);
+ }
+ return woken;
+ }
+
+ basic_condition_variable(const basic_condition_variable& other);
+ basic_condition_variable& operator=(const basic_condition_variable& other);
+ public:
+ basic_condition_variable():
+ total_count(0),active_generation_count(0),wake_sem(0)
+ {
+ for(unsigned i=0;i<generation_count;++i)
+ {
+ generations[i]=list_entry();
+ }
+ }
+
+ ~basic_condition_variable()
+ {
+ for(unsigned i=0;i<generation_count;++i)
+ {
+ dispose_entry(generations[i]);
+ }
+ detail::win32::CloseHandle(wake_sem);
+ }
+
+
+ void notify_one()
+ {
+ if(detail::interlocked_read_acquire(&total_count))
+ {
+ boost::mutex::scoped_lock internal_lock(internal_mutex);
+ detail::win32::ReleaseSemaphore(wake_sem,1,0);
+ for(unsigned generation=active_generation_count;generation!=0;--generation)
+ {
+ list_entry& entry=generations[generation-1];
+ if(entry.count)
+ {
+ detail::interlocked_write_release(&total_count,total_count-1);
+ entry.notified=true;
+ detail::win32::ReleaseSemaphore(entry.semaphore,1,0);
+ if(!--entry.count)
+ {
+ dispose_entry(entry);
+ if(generation==active_generation_count)
+ {
+ --active_generation_count;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void notify_all()
+ {
+ if(detail::interlocked_read_acquire(&total_count))
+ {
+ boost::mutex::scoped_lock internal_lock(internal_mutex);
+ for(unsigned generation=active_generation_count;generation!=0;--generation)
+ {
+ list_entry& entry=generations[generation-1];
+ if(entry.count)
+ {
+ broadcast_entry(entry,true);
+ }
+ }
+ active_generation_count=0;
+ }
+ }
+
+ };
+ }
+
+ class condition_variable:
+ public detail::basic_condition_variable
+ {
+ public:
+ void wait(unique_lock<mutex>& m)
+ {
+ do_wait(m,::boost::detail::get_system_time_sentinel());
+ }
+
+ template<typename predicate_type>
+ void wait(unique_lock<mutex>& m,predicate_type pred)
+ {
+ while(!pred()) wait(m);
+ }
+
+
+ bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
+ {
+ return do_wait(m,wait_until);
+ }
+
+ template<typename predicate_type>
+ bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
+ {
+ while (!pred())
+ {
+ if(!timed_wait(m, wait_until))
+ return false;
+ }
+ return true;
+ }
+ };
+
+ class condition_variable_any:
+ public detail::basic_condition_variable
+ {
+ public:
+ template<typename lock_type>
+ void wait(lock_type& m)
+ {
+ do_wait(m,::boost::detail::get_system_time_sentinel());
+ }
+
+ template<typename lock_type,typename predicate_type>
+ void wait(lock_type& m,predicate_type pred)
+ {
+ while(!pred()) wait(m);
+ }
+
+ template<typename lock_type>
+ bool timed_wait(lock_type& m,boost::system_time const& wait_until)
+ {
+ return do_wait(m,wait_until);
+ }
+
+ template<typename lock_type,typename predicate_type>
+ bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
+ {
+ while (!pred())
+ {
+ if(!timed_wait(m, wait_until))
+ return false;
+ }
+ return true;
+ }
+ };
+
+}
+
+#endif
Modified: trunk/boost/thread/win32/interlocked_read.hpp
==============================================================================
--- trunk/boost/thread/win32/interlocked_read.hpp (original)
+++ trunk/boost/thread/win32/interlocked_read.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -30,6 +30,17 @@
_ReadWriteBarrier();
return res;
}
+
+ inline void interlocked_write_release(long volatile* x,long value)
+ {
+ _ReadWriteBarrier();
+ *x=value;
+ }
+ inline void interlocked_write_release(void* volatile* x,void* value)
+ {
+ _ReadWriteBarrier();
+ *x=value;
+ }
}
}
@@ -49,6 +60,14 @@
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
}
+ inline void interlocked_write_release(long volatile* x,long value)
+ {
+ BOOST_INTERLOCKED_EXCHANGE(x,value);
+ }
+ inline void interlocked_write_release(void* volatile* x,void* value)
+ {
+ BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
+ }
}
}
Modified: trunk/boost/thread/xtime.hpp
==============================================================================
--- trunk/boost/thread/xtime.hpp (original)
+++ trunk/boost/thread/xtime.hpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -1,5 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
+// Copyright (C) 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -39,6 +40,18 @@
xtime_sec_t sec;
xtime_nsec_t nsec;
+
+ operator system_time() const
+ {
+ return boost::posix_time::from_time_t(0)+
+ boost::posix_time::seconds(static_cast<long>(sec))+
+#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
+ boost::posix_time::nanoseconds(nsec);
+#else
+ boost::posix_time::microseconds((nsec+500)/1000);
+#endif
+ }
+
};
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
Modified: trunk/libs/thread/build/Jamfile.v2
==============================================================================
--- trunk/libs/thread/build/Jamfile.v2 (original)
+++ trunk/libs/thread/build/Jamfile.v2 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
@@ -14,8 +14,8 @@
;
CPP_SOURCES =
- barrier
- condition
+# barrier
+# condition
exceptions
# mutex
# once
Deleted: trunk/libs/thread/src/barrier.cpp
==============================================================================
--- trunk/libs/thread/src/barrier.cpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
+++ (empty file)
@@ -1,42 +0,0 @@
-// Copyright (C) 2002-2003
-// David Moore, William E. Kempf
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#include <boost/thread/detail/config.hpp>
-#include <boost/thread/barrier.hpp>
-#include <string> // see http://article.gmane.org/gmane.comp.lib.boost.devel/106981
-
-namespace boost {
-
-barrier::barrier(unsigned int count)
- : m_threshold(count), m_count(count), m_generation(0)
-{
- if (count == 0)
- throw std::invalid_argument("count cannot be zero.");
-}
-
-barrier::~barrier()
-{
-}
-
-bool barrier::wait()
-{
- boost::mutex::scoped_lock lock(m_mutex);
- unsigned int gen = m_generation;
-
- if (--m_count == 0)
- {
- m_generation++;
- m_count = m_threshold;
- m_cond.notify_all();
- return true;
- }
-
- while (gen == m_generation)
- m_cond.wait(lock);
- return false;
-}
-
-} // namespace boost
Deleted: trunk/libs/thread/src/condition.cpp
==============================================================================
--- trunk/libs/thread/src/condition.cpp 2007-10-19 13:40:04 EDT (Fri, 19 Oct 2007)
+++ (empty file)
@@ -1,705 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#include <boost/thread/detail/config.hpp>
-
-#include <boost/thread/condition.hpp>
-#include <boost/thread/xtime.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/thread/exceptions.hpp>
-#include <boost/limits.hpp>
-#include <cassert>
-#include "timeconv.inl"
-
-#if defined(BOOST_HAS_WINTHREADS)
-# ifndef NOMINMAX
-# define NOMINMAX
-# endif
-# include <windows.h>
-#elif defined(BOOST_HAS_PTHREADS)
-# include <errno.h>
-#elif defined(BOOST_HAS_MPTASKS)
-# include <MacErrors.h>
-# include "mac/init.hpp"
-# include "mac/safe.hpp"
-#endif
-
-// The following include can be removed after the bug on QNX
-// has been tracked down. I need this only for debugging
-//#if !defined(NDEBUG) && defined(BOOST_HAS_PTHREADS)
-#include <iostream>
-//#endif
-
-namespace boost {
-
-namespace detail {
-
-#if defined(BOOST_HAS_WINTHREADS)
-condition_impl::condition_impl()
- : m_gone(0), m_blocked(0), m_waiting(0)
-{
- m_gate = reinterpret_cast<void*>(CreateSemaphore(0, 1, 1, 0));
- m_queue = reinterpret_cast<void*>(
- CreateSemaphore(0, 0, (std::numeric_limits<long>::max)(), 0));
- m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0));
-
- if (!m_gate || !m_queue || !m_mutex)
- {
- int res = 0;
- if (m_gate)
- {
- res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
- assert(res);
- }
- if (m_queue)
- {
- res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
- assert(res);
- }
- if (m_mutex)
- {
- res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
- assert(res);
- }
-
- throw thread_resource_error();
- }
-}
-
-condition_impl::~condition_impl()
-{
- int res = 0;
- res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
- assert(res);
- res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
- assert(res);
- res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
- assert(res);
-}
-
-void condition_impl::notify_one()
-{
- unsigned signals = 0;
-
- int res = 0;
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(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<HANDLE>(m_mutex));
- assert(res);
- return;
- }
-
- ++m_waiting;
- --m_blocked;
- signals = 1;
- }
- else
- {
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(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<HANDLE>(m_gate), 1, 0);
- assert(res);
- }
- }
-
- res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
- assert(res);
-
- if (signals)
- {
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
- assert(res);
- }
-}
-
-void condition_impl::notify_all()
-{
- unsigned signals = 0;
-
- int res = 0;
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(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<HANDLE>(m_mutex));
- assert(res);
- return;
- }
-
- m_waiting += (signals = m_blocked);
- m_blocked = 0;
- }
- else
- {
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(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<HANDLE>(m_gate), 1, 0);
- assert(res);
- }
- }
-
- res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
- assert(res);
-
- if (signals)
- {
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
- assert(res);
- }
-}
-
-void condition_impl::enter_wait()
-{
- int res = 0;
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
- assert(res == WAIT_OBJECT_0);
- ++m_blocked;
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
- assert(res);
-}
-
-void condition_impl::do_wait()
-{
- int res = 0;
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
- assert(res == WAIT_OBJECT_0);
-
- unsigned was_waiting=0;
- unsigned was_gone=0;
-
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
- assert(res == WAIT_OBJECT_0);
- was_waiting = m_waiting;
- was_gone = m_gone;
- if (was_waiting != 0)
- {
- if (--m_waiting == 0)
- {
- if (m_blocked != 0)
- {
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(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<unsigned>::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<HANDLE>(m_gate), INFINITE);
- assert(res == WAIT_OBJECT_0);
- m_blocked -= m_gone;
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
- assert(res);
- m_gone = 0;
- }
- res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
- assert(res);
-
- if (was_waiting == 1)
- {
- for (/**/ ; was_gone; --was_gone)
- {
- // better now than spurious later
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
- INFINITE);
- assert(res == WAIT_OBJECT_0);
- }
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
- assert(res);
- }
-}
-
-bool condition_impl::do_timed_wait(const xtime& xt)
-{
- bool ret = false;
- unsigned int res = 0;
-
- for (;;)
- {
- int milliseconds;
- to_duration(xt, milliseconds);
-
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
- milliseconds);
- assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
- ret = (res == WAIT_OBJECT_0);
-
- if (res == WAIT_TIMEOUT)
- {
- xtime cur;
- xtime_get(&cur, TIME_UTC);
- if (xtime_cmp(xt, cur) > 0)
- continue;
- }
-
- break;
- }
-
- unsigned was_waiting=0;
- unsigned was_gone=0;
-
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
- assert(res == WAIT_OBJECT_0);
- was_waiting = m_waiting;
- was_gone = m_gone;
- if (was_waiting != 0)
- {
- if (!ret) // timeout
- {
- if (m_blocked != 0)
- --m_blocked;
- else
- ++m_gone; // count spurious wakeups
- }
- if (--m_waiting == 0)
- {
- if (m_blocked != 0)
- {
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(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<unsigned>::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<HANDLE>(m_gate), INFINITE);
- assert(res == WAIT_OBJECT_0);
- m_blocked -= m_gone;
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
- assert(res);
- m_gone = 0;
- }
- res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
- assert(res);
-
- if (was_waiting == 1)
- {
- for (/**/ ; was_gone; --was_gone)
- {
- // better now than spurious later
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
- INFINITE);
- assert(res == WAIT_OBJECT_0);
- }
- res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
- assert(res);
- }
-
- return ret;
-}
-#elif defined(BOOST_HAS_PTHREADS)
-condition_impl::condition_impl()
-{
- int res = 0;
- res = pthread_cond_init(&m_condition, 0);
- if (res != 0)
- throw thread_resource_error();
- res = pthread_mutex_init(&m_mutex, 0);
- if (res != 0)
- throw thread_resource_error();
-}
-
-condition_impl::~condition_impl()
-{
- int res = 0;
- res = pthread_cond_destroy(&m_condition);
- assert(res == 0);
- res = pthread_mutex_destroy(&m_mutex);
- assert(res == 0);
-}
-
-void condition_impl::notify_one()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
- res = pthread_cond_signal(&m_condition);
- assert(res == 0);
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-}
-
-void condition_impl::notify_all()
-{
- int res = 0;
- res = pthread_mutex_lock(&m_mutex);
- assert(res == 0);
- res = pthread_cond_broadcast(&m_condition);
- assert(res == 0);
- res = pthread_mutex_unlock(&m_mutex);
- assert(res == 0);
-}
-
-void condition_impl::do_wait(pthread_mutex_t* pmutex)
-{
- int res = 0;
- res = pthread_cond_wait(&m_condition, pmutex);
- assert(res == 0);
-}
-
-bool condition_impl::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
-{
- timespec ts;
- to_timespec(xt, ts);
-
- int res = 0;
- res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
-// Test code for QNX debugging, to get information during regressions
-#ifndef NDEBUG
- if (res == EINVAL) {
- boost::xtime now;
- boost::xtime_get(&now, boost::TIME_UTC);
- std::cerr << "now: " << now.sec << " " << now.nsec << std::endl;
- std::cerr << "time: " << time(0) << std::endl;
- std::cerr << "xtime: " << xt.sec << " " << xt.nsec << std::endl;
- std::cerr << "ts: " << ts.tv_sec << " " << ts.tv_nsec << std::endl;
- std::cerr << "pmutex: " << pmutex << std::endl;
- std::cerr << "condition: " << &m_condition << std::endl;
- assert(res != EINVAL);
- }
-#endif
- assert(res == 0 || res == ETIMEDOUT);
-
- return res != ETIMEDOUT;
-}
-#elif defined(BOOST_HAS_MPTASKS)
-
-using threads::mac::detail::safe_enter_critical_region;
-using threads::mac::detail::safe_wait_on_semaphore;
-
-condition_impl::condition_impl()
- : m_gone(0), m_blocked(0), m_waiting(0)
-{
- threads::mac::detail::thread_init();
-
- OSStatus lStatus = noErr;
-
- lStatus = MPCreateSemaphore(1, 1, &m_gate);
- if(lStatus == noErr)
- lStatus = MPCreateSemaphore(ULONG_MAX, 0, &m_queue);
-
- if(lStatus != noErr || !m_gate || !m_queue)
- {
- if (m_gate)
- {
- lStatus = MPDeleteSemaphore(m_gate);
- assert(lStatus == noErr);
- }
- if (m_queue)
- {
- lStatus = MPDeleteSemaphore(m_queue);
- assert(lStatus == noErr);
- }
-
- throw thread_resource_error();
- }
-}
-
-condition_impl::~condition_impl()
-{
- OSStatus lStatus = noErr;
- lStatus = MPDeleteSemaphore(m_gate);
- assert(lStatus == noErr);
- lStatus = MPDeleteSemaphore(m_queue);
- assert(lStatus == noErr);
-}
-
-void condition_impl::notify_one()
-{
- unsigned signals = 0;
-
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-
- if (m_waiting != 0) // the m_gate is already closed
- {
- if (m_blocked == 0)
- {
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- return;
- }
-
- ++m_waiting;
- --m_blocked;
- }
- else
- {
- lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
- assert(lStatus == noErr);
- if (m_blocked > m_gone)
- {
- if (m_gone != 0)
- {
- m_blocked -= m_gone;
- m_gone = 0;
- }
- signals = m_waiting = 1;
- --m_blocked;
- }
- else
- {
- lStatus = MPSignalSemaphore(m_gate);
- assert(lStatus == noErr);
- }
-
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-
- while (signals)
- {
- lStatus = MPSignalSemaphore(m_queue);
- assert(lStatus == noErr);
- --signals;
- }
- }
-}
-
-void condition_impl::notify_all()
-{
- unsigned signals = 0;
-
- OSStatus lStatus = noErr;
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
-
- if (m_waiting != 0) // the m_gate is already closed
- {
- if (m_blocked == 0)
- {
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
- return;
- }
-
- m_waiting += (signals = m_blocked);
- m_blocked = 0;
- }
- else
- {
- lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
- assert(lStatus == noErr);
- 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
- {
- lStatus = MPSignalSemaphore(m_gate);
- assert(lStatus == noErr);
- }
-
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-
- while (signals)
- {
- lStatus = MPSignalSemaphore(m_queue);
- assert(lStatus == noErr);
- --signals;
- }
- }
-}
-
-void condition_impl::enter_wait()
-{
- OSStatus lStatus = noErr;
- lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
- assert(lStatus == noErr);
- ++m_blocked;
- lStatus = MPSignalSemaphore(m_gate);
- assert(lStatus == noErr);
-}
-
-void condition_impl::do_wait()
-{
- OSStatus lStatus = noErr;
- lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
- assert(lStatus == noErr);
-
- unsigned was_waiting=0;
- unsigned was_gone=0;
-
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
- was_waiting = m_waiting;
- was_gone = m_gone;
- if (was_waiting != 0)
- {
- if (--m_waiting == 0)
- {
- if (m_blocked != 0)
- {
- lStatus = MPSignalSemaphore(m_gate); // open m_gate
- assert(lStatus == noErr);
- was_waiting = 0;
- }
- else if (m_gone != 0)
- m_gone = 0;
- }
- }
- else if (++m_gone == ((std::numeric_limits<unsigned>::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
- lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
- assert(lStatus == noErr);
- m_blocked -= m_gone;
- lStatus = MPSignalSemaphore(m_gate);
- assert(lStatus == noErr);
- m_gone = 0;
- }
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-
- if (was_waiting == 1)
- {
- for (/**/ ; was_gone; --was_gone)
- {
- // better now than spurious later
- lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
- assert(lStatus == noErr);
- }
- lStatus = MPSignalSemaphore(m_gate);
- assert(lStatus == noErr);
- }
-}
-
-bool condition_impl::do_timed_wait(const xtime& xt)
-{
- int milliseconds;
- to_duration(xt, milliseconds);
-
- OSStatus lStatus = noErr;
- lStatus = safe_wait_on_semaphore(m_queue, milliseconds);
- assert(lStatus == noErr || lStatus == kMPTimeoutErr);
-
- bool ret = (lStatus == noErr);
-
- unsigned was_waiting=0;
- unsigned was_gone=0;
-
- lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
- m_mutex_mutex);
- assert(lStatus == noErr);
- was_waiting = m_waiting;
- was_gone = m_gone;
- if (was_waiting != 0)
- {
- if (!ret) // timeout
- {
- if (m_blocked != 0)
- --m_blocked;
- else
- ++m_gone; // count spurious wakeups
- }
- if (--m_waiting == 0)
- {
- if (m_blocked != 0)
- {
- lStatus = MPSignalSemaphore(m_gate); // open m_gate
- assert(lStatus == noErr);
- was_waiting = 0;
- }
- else if (m_gone != 0)
- m_gone = 0;
- }
- }
- else if (++m_gone == ((std::numeric_limits<unsigned>::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
- lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
- assert(lStatus == noErr);
- m_blocked -= m_gone;
- lStatus = MPSignalSemaphore(m_gate);
- assert(lStatus == noErr);
- m_gone = 0;
- }
- lStatus = MPExitCriticalRegion(m_mutex);
- assert(lStatus == noErr);
-
- if (was_waiting == 1)
- {
- for (/**/ ; was_gone; --was_gone)
- {
- // better now than spurious later
- lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
- assert(lStatus == noErr);
- }
- lStatus = MPSignalSemaphore(m_gate);
- assert(lStatus == noErr);
- }
-
- return ret;
-}
-#endif
-
-} // namespace detail
-
-} // namespace boost
-
-// Change Log:
-// 8 Feb 01 WEKEMPF Initial version.
-// 22 May 01 WEKEMPF Modified to use xtime for time outs.
-// 3 Jan 03 WEKEMPF Modified for DLL implementation.
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk