mirror of
https://github.com/boostorg/thread.git
synced 2026-02-08 11:12:23 +00:00
Compare commits
3 Commits
develop
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83d2bb6716 | ||
|
|
b937d909e9 | ||
|
|
94d9b1b288 |
@@ -14,8 +14,8 @@ project boost/thread
|
|||||||
;
|
;
|
||||||
|
|
||||||
CPP_SOURCES =
|
CPP_SOURCES =
|
||||||
barrier
|
# barrier
|
||||||
condition
|
# condition
|
||||||
exceptions
|
exceptions
|
||||||
# mutex
|
# mutex
|
||||||
# once
|
# once
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (C) 2002-2003
|
// Copyright (C) 2002-2003
|
||||||
// David Moore, William E. Kempf
|
// David Moore, William E. Kempf
|
||||||
|
// Copyright (C) 2007 Anthony Williams
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// 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)
|
// 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/mutex.hpp>
|
||||||
#include <boost/thread/condition.hpp>
|
#include <boost/thread/condition.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost
|
||||||
|
|
||||||
class BOOST_THREAD_DECL barrier
|
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
barrier(unsigned int count);
|
|
||||||
~barrier();
|
|
||||||
|
|
||||||
bool wait();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
while (gen == m_generation)
|
||||||
mutex m_mutex;
|
m_cond.wait(lock);
|
||||||
// disable warnings about non dll import
|
return false;
|
||||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
}
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
# pragma warning(push)
|
private:
|
||||||
# pragma warning(disable: 4251 4231 4660 4275)
|
mutex m_mutex;
|
||||||
#endif
|
condition m_cond;
|
||||||
condition m_cond;
|
unsigned int m_threshold;
|
||||||
#ifdef BOOST_MSVC
|
unsigned int m_count;
|
||||||
# pragma warning(pop)
|
unsigned int m_generation;
|
||||||
#endif
|
};
|
||||||
unsigned int m_threshold;
|
|
||||||
unsigned int m_count;
|
|
||||||
unsigned int m_generation;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
|
|||||||
@@ -1,197 +1,10 @@
|
|||||||
// Copyright (C) 2001-2003
|
#ifndef BOOST_THREAD_CONDITION_HPP
|
||||||
// William E. Kempf
|
#define BOOST_THREAD_CONDITION_HPP
|
||||||
// Copyright (C) 2007 Anthony Williams
|
#include <boost/thread/condition_variable.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)
|
|
||||||
|
|
||||||
#ifndef BOOST_CONDITION_WEK070601_HPP
|
namespace boost
|
||||||
#define BOOST_CONDITION_WEK070601_HPP
|
|
||||||
|
|
||||||
#include <boost/thread/detail/config.hpp>
|
|
||||||
|
|
||||||
#include <boost/thread/exceptions.hpp>
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
#include <boost/thread/detail/lock.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
|
|
||||||
{
|
{
|
||||||
friend class condition;
|
typedef condition_variable_any 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
|
#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());
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|||||||
15
include/boost/thread/condition_variable.hpp
Normal file
15
include/boost/thread/condition_variable.hpp
Normal file
@@ -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
|
||||||
@@ -1,209 +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)
|
|
||||||
|
|
||||||
#ifndef BOOST_XLOCK_WEK070601_HPP
|
|
||||||
#define BOOST_XLOCK_WEK070601_HPP
|
|
||||||
|
|
||||||
#include <boost/thread/detail/config.hpp>
|
|
||||||
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
#include <boost/thread/exceptions.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
class condition;
|
|
||||||
struct xtime;
|
|
||||||
|
|
||||||
namespace detail { namespace thread {
|
|
||||||
|
|
||||||
template <typename Mutex>
|
|
||||||
class lock_ops : private noncopyable
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
lock_ops() { }
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename Mutex::cv_state lock_state;
|
|
||||||
|
|
||||||
static void lock(Mutex& m)
|
|
||||||
{
|
|
||||||
m.do_lock();
|
|
||||||
}
|
|
||||||
static bool trylock(Mutex& m)
|
|
||||||
{
|
|
||||||
return m.do_trylock();
|
|
||||||
}
|
|
||||||
static bool timedlock(Mutex& m, const xtime& xt)
|
|
||||||
{
|
|
||||||
return m.do_timedlock(xt);
|
|
||||||
}
|
|
||||||
static void unlock(Mutex& m)
|
|
||||||
{
|
|
||||||
m.do_unlock();
|
|
||||||
}
|
|
||||||
static void lock(Mutex& m, lock_state& state)
|
|
||||||
{
|
|
||||||
m.do_lock(state);
|
|
||||||
}
|
|
||||||
static void unlock(Mutex& m, lock_state& state)
|
|
||||||
{
|
|
||||||
m.do_unlock(state);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Mutex>
|
|
||||||
class scoped_lock : private noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef Mutex mutex_type;
|
|
||||||
|
|
||||||
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
|
|
||||||
: m_mutex(mx), m_locked(false)
|
|
||||||
{
|
|
||||||
if (initially_locked) lock();
|
|
||||||
}
|
|
||||||
~scoped_lock()
|
|
||||||
{
|
|
||||||
if (m_locked) unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void lock()
|
|
||||||
{
|
|
||||||
if (m_locked) throw lock_error();
|
|
||||||
lock_ops<Mutex>::lock(m_mutex);
|
|
||||||
m_locked = true;
|
|
||||||
}
|
|
||||||
void unlock()
|
|
||||||
{
|
|
||||||
if (!m_locked) throw lock_error();
|
|
||||||
lock_ops<Mutex>::unlock(m_mutex);
|
|
||||||
m_locked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool locked() const { return m_locked; }
|
|
||||||
operator const void*() const { return m_locked ? this : 0; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class boost::condition;
|
|
||||||
|
|
||||||
Mutex& m_mutex;
|
|
||||||
bool m_locked;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TryMutex>
|
|
||||||
class scoped_try_lock : private noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef TryMutex mutex_type;
|
|
||||||
|
|
||||||
explicit scoped_try_lock(TryMutex& mx)
|
|
||||||
: m_mutex(mx), m_locked(false)
|
|
||||||
{
|
|
||||||
try_lock();
|
|
||||||
}
|
|
||||||
scoped_try_lock(TryMutex& mx, bool initially_locked)
|
|
||||||
: m_mutex(mx), m_locked(false)
|
|
||||||
{
|
|
||||||
if (initially_locked) lock();
|
|
||||||
}
|
|
||||||
~scoped_try_lock()
|
|
||||||
{
|
|
||||||
if (m_locked) unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void lock()
|
|
||||||
{
|
|
||||||
if (m_locked) throw lock_error();
|
|
||||||
lock_ops<TryMutex>::lock(m_mutex);
|
|
||||||
m_locked = true;
|
|
||||||
}
|
|
||||||
bool try_lock()
|
|
||||||
{
|
|
||||||
if (m_locked) throw lock_error();
|
|
||||||
return (m_locked = lock_ops<TryMutex>::trylock(m_mutex));
|
|
||||||
}
|
|
||||||
void unlock()
|
|
||||||
{
|
|
||||||
if (!m_locked) throw lock_error();
|
|
||||||
lock_ops<TryMutex>::unlock(m_mutex);
|
|
||||||
m_locked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool locked() const { return m_locked; }
|
|
||||||
operator const void*() const { return m_locked ? this : 0; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class boost::condition;
|
|
||||||
|
|
||||||
TryMutex& m_mutex;
|
|
||||||
bool m_locked;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TimedMutex>
|
|
||||||
class scoped_timed_lock : private noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef TimedMutex mutex_type;
|
|
||||||
|
|
||||||
scoped_timed_lock(TimedMutex& mx, const xtime& xt)
|
|
||||||
: m_mutex(mx), m_locked(false)
|
|
||||||
{
|
|
||||||
timed_lock(xt);
|
|
||||||
}
|
|
||||||
scoped_timed_lock(TimedMutex& mx, bool initially_locked)
|
|
||||||
: m_mutex(mx), m_locked(false)
|
|
||||||
{
|
|
||||||
if (initially_locked) lock();
|
|
||||||
}
|
|
||||||
~scoped_timed_lock()
|
|
||||||
{
|
|
||||||
if (m_locked) unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void lock()
|
|
||||||
{
|
|
||||||
if (m_locked) throw lock_error();
|
|
||||||
lock_ops<TimedMutex>::lock(m_mutex);
|
|
||||||
m_locked = true;
|
|
||||||
}
|
|
||||||
bool try_lock()
|
|
||||||
{
|
|
||||||
if (m_locked) throw lock_error();
|
|
||||||
return (m_locked = lock_ops<TimedMutex>::trylock(m_mutex));
|
|
||||||
}
|
|
||||||
bool timed_lock(const xtime& xt)
|
|
||||||
{
|
|
||||||
if (m_locked) throw lock_error();
|
|
||||||
return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt));
|
|
||||||
}
|
|
||||||
void unlock()
|
|
||||||
{
|
|
||||||
if (!m_locked) throw lock_error();
|
|
||||||
lock_ops<TimedMutex>::unlock(m_mutex);
|
|
||||||
m_locked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool locked() const { return m_locked; }
|
|
||||||
operator const void*() const { return m_locked ? this : 0; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class boost::condition;
|
|
||||||
|
|
||||||
TimedMutex& m_mutex;
|
|
||||||
bool m_locked;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace thread
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_XLOCK_WEK070601_HPP
|
|
||||||
|
|
||||||
// Change Log:
|
|
||||||
// 8 Feb 01 WEKEMPF Initial version.
|
|
||||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
|
||||||
// 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed
|
|
||||||
// some types. Added locked() methods.
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (C) 2001-2003
|
// Copyright (C) 2001-2003
|
||||||
// William E. Kempf
|
// William E. Kempf
|
||||||
|
// Copyright (C) 2007 Anthony Williams
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// 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)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@@ -35,6 +36,17 @@ private:
|
|||||||
int m_sys_err;
|
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
|
class BOOST_THREAD_DECL lock_error : public thread_exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
194
include/boost/thread/pthread/condition_variable.hpp
Normal file
194
include/boost/thread/pthread/condition_variable.hpp
Normal file
@@ -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
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "timespec.hpp"
|
#include "timespec.hpp"
|
||||||
|
#include "pthread_mutex_scoped_lock.hpp"
|
||||||
|
|
||||||
#ifdef _POSIX_TIMEOUTS
|
#ifdef _POSIX_TIMEOUTS
|
||||||
#if _POSIX_TIMEOUTS >= 0
|
#if _POSIX_TIMEOUTS >= 0
|
||||||
@@ -61,6 +62,13 @@ namespace boost
|
|||||||
BOOST_ASSERT(!res || res==EBUSY);
|
BOOST_ASSERT(!res || res==EBUSY);
|
||||||
return !res;
|
return !res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef pthread_mutex_t* native_handle_type;
|
||||||
|
native_handle_type native_handle() const
|
||||||
|
{
|
||||||
|
return &m;
|
||||||
|
}
|
||||||
|
|
||||||
typedef unique_lock<mutex> scoped_lock;
|
typedef unique_lock<mutex> scoped_lock;
|
||||||
typedef scoped_lock scoped_try_lock;
|
typedef scoped_lock scoped_try_lock;
|
||||||
};
|
};
|
||||||
@@ -75,25 +83,6 @@ namespace boost
|
|||||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
bool is_locked;
|
bool is_locked;
|
||||||
|
|
||||||
struct pthread_mutex_scoped_lock
|
|
||||||
{
|
|
||||||
pthread_mutex_t* m;
|
|
||||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
|
|
||||||
m(m_)
|
|
||||||
{
|
|
||||||
int const res=pthread_mutex_lock(m);
|
|
||||||
BOOST_ASSERT(!res);
|
|
||||||
}
|
|
||||||
~pthread_mutex_scoped_lock()
|
|
||||||
{
|
|
||||||
int const res=pthread_mutex_unlock(m);
|
|
||||||
BOOST_ASSERT(!res);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
timed_mutex()
|
timed_mutex()
|
||||||
@@ -159,7 +148,7 @@ namespace boost
|
|||||||
#else
|
#else
|
||||||
void lock()
|
void lock()
|
||||||
{
|
{
|
||||||
pthread_mutex_scoped_lock const _(&m);
|
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||||
while(is_locked)
|
while(is_locked)
|
||||||
{
|
{
|
||||||
int const cond_res=pthread_cond_wait(&cond,&m);
|
int const cond_res=pthread_cond_wait(&cond,&m);
|
||||||
@@ -170,7 +159,7 @@ namespace boost
|
|||||||
|
|
||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
pthread_mutex_scoped_lock const _(&m);
|
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||||
is_locked=false;
|
is_locked=false;
|
||||||
int const res=pthread_cond_signal(&cond);
|
int const res=pthread_cond_signal(&cond);
|
||||||
BOOST_ASSERT(!res);
|
BOOST_ASSERT(!res);
|
||||||
@@ -178,7 +167,7 @@ namespace boost
|
|||||||
|
|
||||||
bool try_lock()
|
bool try_lock()
|
||||||
{
|
{
|
||||||
pthread_mutex_scoped_lock const _(&m);
|
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||||
if(is_locked)
|
if(is_locked)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -190,7 +179,7 @@ namespace boost
|
|||||||
bool timed_lock(system_time const & abs_time)
|
bool timed_lock(system_time const & abs_time)
|
||||||
{
|
{
|
||||||
struct timespec const timeout=detail::get_timespec(abs_time);
|
struct timespec const timeout=detail::get_timespec(abs_time);
|
||||||
pthread_mutex_scoped_lock const _(&m);
|
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||||
while(is_locked)
|
while(is_locked)
|
||||||
{
|
{
|
||||||
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
|
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
|
||||||
|
|||||||
30
include/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
Normal file
30
include/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
|
||||||
|
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
namespace pthread
|
||||||
|
{
|
||||||
|
class pthread_mutex_scoped_lock
|
||||||
|
{
|
||||||
|
pthread_mutex_t* m;
|
||||||
|
public:
|
||||||
|
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
|
||||||
|
m(m_)
|
||||||
|
{
|
||||||
|
int const res=pthread_mutex_lock(m);
|
||||||
|
BOOST_ASSERT(!res);
|
||||||
|
}
|
||||||
|
~pthread_mutex_scoped_lock()
|
||||||
|
{
|
||||||
|
int const res=pthread_mutex_unlock(m);
|
||||||
|
BOOST_ASSERT(!res);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <boost/date_time/posix_time/conversion.hpp>
|
#include <boost/date_time/posix_time/conversion.hpp>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "timespec.hpp"
|
#include "timespec.hpp"
|
||||||
|
#include "pthread_mutex_scoped_lock.hpp"
|
||||||
|
|
||||||
#ifdef _POSIX_TIMEOUTS
|
#ifdef _POSIX_TIMEOUTS
|
||||||
#if _POSIX_TIMEOUTS >= 0
|
#if _POSIX_TIMEOUTS >= 0
|
||||||
@@ -93,25 +94,6 @@ namespace boost
|
|||||||
bool is_locked;
|
bool is_locked;
|
||||||
pthread_t owner;
|
pthread_t owner;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
|
|
||||||
struct pthread_mutex_scoped_lock
|
|
||||||
{
|
|
||||||
pthread_mutex_t* m;
|
|
||||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
|
|
||||||
m(m_)
|
|
||||||
{
|
|
||||||
int const res=pthread_mutex_lock(m);
|
|
||||||
BOOST_ASSERT(!res);
|
|
||||||
}
|
|
||||||
~pthread_mutex_scoped_lock()
|
|
||||||
{
|
|
||||||
int const res=pthread_mutex_unlock(m);
|
|
||||||
BOOST_ASSERT(!res);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
recursive_timed_mutex()
|
recursive_timed_mutex()
|
||||||
@@ -201,7 +183,7 @@ namespace boost
|
|||||||
#else
|
#else
|
||||||
void lock()
|
void lock()
|
||||||
{
|
{
|
||||||
pthread_mutex_scoped_lock const _(&m);
|
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||||
if(is_locked && owner==pthread_self())
|
if(is_locked && owner==pthread_self())
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
@@ -220,7 +202,7 @@ namespace boost
|
|||||||
|
|
||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
pthread_mutex_scoped_lock const _(&m);
|
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||||
if(!--count)
|
if(!--count)
|
||||||
{
|
{
|
||||||
is_locked=false;
|
is_locked=false;
|
||||||
@@ -231,7 +213,7 @@ namespace boost
|
|||||||
|
|
||||||
bool try_lock()
|
bool try_lock()
|
||||||
{
|
{
|
||||||
pthread_mutex_scoped_lock const _(&m);
|
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||||
if(is_locked && owner!=pthread_self())
|
if(is_locked && owner!=pthread_self())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -245,7 +227,7 @@ namespace boost
|
|||||||
bool timed_lock(system_time const & abs_time)
|
bool timed_lock(system_time const & abs_time)
|
||||||
{
|
{
|
||||||
struct timespec const timeout=detail::get_timespec(abs_time);
|
struct timespec const timeout=detail::get_timespec(abs_time);
|
||||||
pthread_mutex_scoped_lock const _(&m);
|
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||||
if(is_locked && owner==pthread_self())
|
if(is_locked && owner==pthread_self())
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include <boost/static_assert.hpp>
|
#include <boost/static_assert.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/thread/condition.hpp>
|
#include <boost/thread/condition.hpp>
|
||||||
#include <boost/thread/xtime.hpp>
|
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
@@ -95,7 +94,7 @@ namespace boost
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!shared_cond.timed_wait(lock,get_xtime(timeout)))
|
if(!shared_cond.timed_wait(lock,timeout))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -157,7 +156,7 @@ namespace boost
|
|||||||
state.exclusive=true;
|
state.exclusive=true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(!exclusive_cond.timed_wait(lock,get_xtime(timeout)))
|
if(!exclusive_cond.timed_wait(lock,timeout))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -216,7 +215,7 @@ namespace boost
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!shared_cond.timed_wait(lock,get_xtime(timeout)))
|
if(!shared_cond.timed_wait(lock,timeout))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
#if defined(BOOST_HAS_PTHREADS)
|
#if defined(BOOST_HAS_PTHREADS)
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
# include <boost/thread/condition.hpp>
|
|
||||||
#elif defined(BOOST_HAS_MPTASKS)
|
#elif defined(BOOST_HAS_MPTASKS)
|
||||||
# include <Multiprocessing.h>
|
# include <Multiprocessing.h>
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,18 +19,18 @@ namespace boost
|
|||||||
return system_time(boost::posix_time::pos_infin);
|
return system_time(boost::posix_time::pos_infin);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned get_milliseconds_until(system_time const& target_time)
|
inline unsigned long get_milliseconds_until(system_time const& target_time)
|
||||||
{
|
{
|
||||||
if(target_time.is_pos_infinity())
|
if(target_time.is_pos_infinity())
|
||||||
{
|
{
|
||||||
return ~0u;
|
return ~(unsigned long)0;
|
||||||
}
|
}
|
||||||
system_time const now=get_system_time();
|
system_time const now=get_system_time();
|
||||||
if(target_time<=now)
|
if(target_time<=now)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (target_time-now).total_milliseconds()+1;
|
return static_cast<unsigned long>((target_time-now).total_milliseconds()+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "thread_primitives.hpp"
|
#include "thread_primitives.hpp"
|
||||||
#include "interlocked_read.hpp"
|
#include "interlocked_read.hpp"
|
||||||
#include <boost/thread/thread_time.hpp>
|
#include <boost/thread/thread_time.hpp>
|
||||||
|
#include <boost/detail/interlocked.hpp>
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
@@ -112,7 +113,7 @@ namespace boost
|
|||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
long const offset=lock_flag_value+1;
|
long const offset=lock_flag_value+1;
|
||||||
long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,-offset);
|
long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,(~offset)+1);
|
||||||
|
|
||||||
if(old_count>offset)
|
if(old_count>offset)
|
||||||
{
|
{
|
||||||
|
|||||||
309
include/boost/thread/win32/condition_variable.hpp
Normal file
309
include/boost/thread/win32/condition_variable.hpp
Normal file
@@ -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
|
||||||
@@ -30,6 +30,17 @@ namespace boost
|
|||||||
_ReadWriteBarrier();
|
_ReadWriteBarrier();
|
||||||
return res;
|
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 @@ namespace boost
|
|||||||
{
|
{
|
||||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (C) 2001-2003
|
// Copyright (C) 2001-2003
|
||||||
// William E. Kempf
|
// William E. Kempf
|
||||||
|
// Copyright (C) 2007 Anthony Williams
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// 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)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@@ -39,6 +40,18 @@ struct xtime
|
|||||||
|
|
||||||
xtime_sec_t sec;
|
xtime_sec_t sec;
|
||||||
xtime_nsec_t nsec;
|
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);
|
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
|
||||||
@@ -56,8 +69,8 @@ inline xtime get_xtime(boost::system_time const& abs_time)
|
|||||||
xtime res={0};
|
xtime res={0};
|
||||||
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
|
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
|
||||||
|
|
||||||
res.sec=time_since_epoch.total_seconds();
|
res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds());
|
||||||
res.nsec=time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second());
|
res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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.
|
|
||||||
Reference in New Issue
Block a user