|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r49324 - in branches/release: boost/thread boost/thread/detail boost/thread/pthread boost/thread/win32 libs/thread/doc libs/thread/src/win32 libs/thread/test
From: anthony_at_[hidden]
Date: 2008-10-13 16:30:14
Author: anthonyw
Date: 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
New Revision: 49324
URL: http://svn.boost.org/trac/boost/changeset/49324
Log:
Merged Boost.Thread changes from trunk
Text files modified:
branches/release/boost/thread/detail/move.hpp | 4
branches/release/boost/thread/detail/thread.hpp | 4
branches/release/boost/thread/locks.hpp | 6
branches/release/boost/thread/pthread/recursive_mutex.hpp | 2
branches/release/boost/thread/pthread/shared_mutex.hpp | 46 ++--
branches/release/boost/thread/win32/basic_recursive_mutex.hpp | 10 -
branches/release/boost/thread/win32/basic_timed_mutex.hpp | 10 -
branches/release/libs/thread/doc/changes.qbk | 3
branches/release/libs/thread/src/win32/thread.cpp | 22 +
branches/release/libs/thread/src/win32/tss_pe.cpp | 46 +++-
branches/release/libs/thread/test/test_mutex.cpp | 84 +++++++++
branches/release/libs/thread/test/test_thread_move.cpp | 47 ++++
branches/release/libs/thread/test/util.inl | 366 ++++++++++++++++++++--------------------
13 files changed, 395 insertions(+), 255 deletions(-)
Modified: branches/release/boost/thread/detail/move.hpp
==============================================================================
--- branches/release/boost/thread/detail/move.hpp (original)
+++ branches/release/boost/thread/detail/move.hpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -41,9 +41,9 @@
#ifndef BOOST_NO_SFINAE
template<typename T>
- typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, detail::thread_move_t<T> >::type move(T& t)
+ typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, T >::type move(T& t)
{
- return t;
+ return T(detail::thread_move_t<T>(t));
}
#endif
Modified: branches/release/boost/thread/detail/thread.hpp
==============================================================================
--- branches/release/boost/thread/detail/thread.hpp (original)
+++ branches/release/boost/thread/detail/thread.hpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -339,9 +339,9 @@
return t;
}
#else
- inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
+ inline thread move(detail::thread_move_t<thread> t)
{
- return t;
+ return thread(t);
}
#endif
Modified: branches/release/boost/thread/locks.hpp
==============================================================================
--- branches/release/boost/thread/locks.hpp (original)
+++ branches/release/boost/thread/locks.hpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -234,6 +234,12 @@
{
try_lock();
}
+ template<typename TimeDuration>
+ unique_lock(Mutex& m_,TimeDuration const& target_time):
+ m(&m_),is_locked(false)
+ {
+ timed_lock(target_time);
+ }
unique_lock(Mutex& m_,system_time const& target_time):
m(&m_),is_locked(false)
{
Modified: branches/release/boost/thread/pthread/recursive_mutex.hpp
==============================================================================
--- branches/release/boost/thread/pthread/recursive_mutex.hpp (original)
+++ branches/release/boost/thread/pthread/recursive_mutex.hpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -177,7 +177,7 @@
{
struct timespec const timeout=detail::get_timespec(abs_time);
int const res=pthread_mutex_timedlock(&m,&timeout);
- BOOST_ASSERT(!res || res==EBUSY);
+ BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
Modified: branches/release/boost/thread/pthread/shared_mutex.hpp
==============================================================================
--- branches/release/boost/thread/pthread/shared_mutex.hpp (original)
+++ branches/release/boost/thread/pthread/shared_mutex.hpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -57,18 +57,18 @@
void lock_shared()
{
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
- shared_cond.wait(lock);
+ shared_cond.wait(lk);
}
++state.shared_count;
}
bool try_lock_shared()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked)
{
@@ -84,11 +84,11 @@
bool timed_lock_shared(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
- if(!shared_cond.timed_wait(lock,timeout))
+ if(!shared_cond.timed_wait(lk,timeout))
{
return false;
}
@@ -105,7 +105,7 @@
void unlock_shared()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
bool const last_reader=!--state.shared_count;
if(last_reader)
@@ -127,12 +127,12 @@
void lock()
{
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
- exclusive_cond.wait(lock);
+ exclusive_cond.wait(lk);
}
state.exclusive=true;
}
@@ -140,12 +140,12 @@
bool timed_lock(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
- if(!exclusive_cond.timed_wait(lock,timeout))
+ if(!exclusive_cond.timed_wait(lk,timeout))
{
if(state.shared_count || state.exclusive)
{
@@ -168,7 +168,7 @@
bool try_lock()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
if(state.shared_count || state.exclusive)
{
@@ -184,7 +184,7 @@
void unlock()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
state.exclusive=false;
state.exclusive_waiting_blocked=false;
release_waiters();
@@ -193,10 +193,10 @@
void lock_upgrade()
{
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
- shared_cond.wait(lock);
+ shared_cond.wait(lk);
}
++state.shared_count;
state.upgrade=true;
@@ -205,10 +205,10 @@
bool timed_lock_upgrade(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
- if(!shared_cond.timed_wait(lock,timeout))
+ if(!shared_cond.timed_wait(lk,timeout))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
@@ -230,7 +230,7 @@
bool try_lock_upgrade()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
@@ -245,7 +245,7 @@
void unlock_upgrade()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
state.upgrade=false;
bool const last_reader=!--state.shared_count;
@@ -259,11 +259,11 @@
void unlock_upgrade_and_lock()
{
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
--state.shared_count;
while(state.shared_count)
{
- upgrade_cond.wait(lock);
+ upgrade_cond.wait(lk);
}
state.upgrade=false;
state.exclusive=true;
@@ -271,7 +271,7 @@
void unlock_and_lock_upgrade()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
state.exclusive=false;
state.upgrade=true;
++state.shared_count;
@@ -281,7 +281,7 @@
void unlock_and_lock_shared()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
state.exclusive=false;
++state.shared_count;
state.exclusive_waiting_blocked=false;
@@ -290,7 +290,7 @@
void unlock_upgrade_and_lock_shared()
{
- boost::mutex::scoped_lock lock(state_change);
+ boost::mutex::scoped_lock lk(state_change);
state.upgrade=false;
state.exclusive_waiting_blocked=false;
release_waiters();
Modified: branches/release/boost/thread/win32/basic_recursive_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/basic_recursive_mutex.hpp (original)
+++ branches/release/boost/thread/win32/basic_recursive_mutex.hpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -64,11 +64,6 @@
return timed_lock(get_system_time()+timeout);
}
- long get_active_count()
- {
- return mutex.get_active_count();
- }
-
void unlock()
{
if(!--recursion_count)
@@ -78,11 +73,6 @@
}
}
- bool locked()
- {
- return mutex.locked();
- }
-
private:
bool try_recursive_lock(long current_thread_id)
{
Modified: branches/release/boost/thread/win32/basic_timed_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/basic_timed_mutex.hpp (original)
+++ branches/release/boost/thread/win32/basic_timed_mutex.hpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -123,11 +123,6 @@
return timed_lock(system_time(timeout));
}
- long get_active_count()
- {
- return ::boost::detail::interlocked_read_acquire(&active_count);
- }
-
void unlock()
{
long const offset=lock_flag_value;
@@ -141,11 +136,6 @@
}
}
- bool locked()
- {
- return get_active_count()>=lock_flag_value;
- }
-
private:
void* get_event()
{
Modified: branches/release/libs/thread/doc/changes.qbk
==============================================================================
--- branches/release/libs/thread/doc/changes.qbk (original)
+++ branches/release/libs/thread/doc/changes.qbk 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -77,4 +77,7 @@
* __mutex__ is now never recursive. For Boost releases prior to 1.35 __mutex__ was recursive on Windows and not on POSIX platforms.
+* When using a __recursive_mutex__ with a call to [cond_any_wait_link `boost::condition_variable_any::wait()`], the mutex is only
+ unlocked one level, and not completely. This prior behaviour was not guaranteed and did not feature in the tests.
+
[endsect]
Modified: branches/release/libs/thread/src/win32/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/thread.cpp (original)
+++ branches/release/libs/thread/src/win32/thread.cpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -29,13 +29,26 @@
void create_current_thread_tls_key()
{
+ tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
current_thread_tls_key=TlsAlloc();
BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
}
+ void cleanup_tls_key()
+ {
+ if(current_thread_tls_key)
+ {
+ TlsFree(current_thread_tls_key);
+ current_thread_tls_key=0;
+ }
+ }
+
detail::thread_data_base* get_current_thread_data()
{
- boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
+ if(!current_thread_tls_key)
+ {
+ return 0;
+ }
return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
}
@@ -141,8 +154,8 @@
}
}
+ set_current_thread_data(0);
}
- set_current_thread_data(0);
}
unsigned __stdcall thread_start_function(void* param)
@@ -544,7 +557,6 @@
void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)
{
- tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
if(tss_data_node* const current_node=find_tss_data(key))
{
if(cleanup_existing && current_node->func.get())
@@ -572,7 +584,9 @@
{}
extern "C" BOOST_THREAD_DECL void on_process_exit()
-{}
+{
+ boost::cleanup_tls_key();
+}
extern "C" BOOST_THREAD_DECL void on_thread_exit()
{
Modified: branches/release/libs/thread/src/win32/tss_pe.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/tss_pe.cpp (original)
+++ branches/release/libs/thread/src/win32/tss_pe.cpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -26,11 +26,11 @@
{
switch (dwReason)
{
- case DLL_THREAD_DETACH:
- {
- on_thread_exit();
- break;
- }
+ case DLL_THREAD_DETACH:
+ {
+ on_thread_exit();
+ break;
+ }
}
}
@@ -125,10 +125,10 @@
#pragma section(".CRT$XCU",long,read)
#pragma section(".CRT$XTU",long,read)
#pragma section(".CRT$XLC",long,read)
- static __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback;
- static __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare;
- static __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init;
- static __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term;
+ __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback;
+ __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare;
+ __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init;
+ __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term;
#else
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
# pragma data_seg(push, old_seg)
@@ -168,6 +168,7 @@
#pragma warning(push)
#pragma warning(disable:4189)
#endif
+
PVAPI on_tls_prepare(void)
{
//The following line has an important side effect:
@@ -239,15 +240,32 @@
{
switch (dwReason)
{
- case DLL_THREAD_DETACH:
- {
- on_thread_exit();
- break;
- }
+ case DLL_THREAD_DETACH:
+ on_thread_exit();
+ break;
}
}
+
+ BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID)
+ {
+ switch (dwReason)
+ {
+ case DLL_THREAD_DETACH:
+ on_thread_exit();
+ break;
+ case DLL_PROCESS_DETACH:
+ on_process_exit();
+ break;
+ }
+ return true;
+ }
} //namespace
+extern "C"
+{
+ extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback;
+}
+
extern "C" void tss_cleanup_implemented(void)
{
/*
Modified: branches/release/libs/thread/test/test_mutex.cpp
==============================================================================
--- branches/release/libs/thread/test/test_mutex.cpp (original)
+++ branches/release/libs/thread/test/test_mutex.cpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -7,6 +7,7 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/condition.hpp>
@@ -96,6 +97,86 @@
}
};
+template<typename Mutex>
+struct test_lock_times_out_if_other_thread_has_lock
+{
+ typedef boost::unique_lock<Mutex> Lock;
+
+ Mutex m;
+ boost::mutex done_mutex;
+ bool done;
+ bool locked;
+ boost::condition_variable done_cond;
+
+ test_lock_times_out_if_other_thread_has_lock():
+ done(false),locked(false)
+ {}
+
+ void locking_thread()
+ {
+ Lock lock(m,boost::defer_lock);
+ lock.timed_lock(boost::posix_time::milliseconds(50));
+
+ boost::lock_guard<boost::mutex> lk(done_mutex);
+ locked=lock.owns_lock();
+ done=true;
+ done_cond.notify_one();
+ }
+
+ void locking_thread_through_constructor()
+ {
+ Lock lock(m,boost::posix_time::milliseconds(50));
+
+ boost::lock_guard<boost::mutex> lk(done_mutex);
+ locked=lock.owns_lock();
+ done=true;
+ done_cond.notify_one();
+ }
+
+ bool is_done() const
+ {
+ return done;
+ }
+
+ typedef test_lock_times_out_if_other_thread_has_lock<Mutex> this_type;
+
+ void do_test(void (this_type::*test_func)())
+ {
+ Lock lock(m);
+
+ locked=false;
+ done=false;
+
+ boost::thread t(test_func,this);
+
+ try
+ {
+ {
+ boost::mutex::scoped_lock lk(done_mutex);
+ BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
+ boost::bind(&this_type::is_done,this)));
+ BOOST_CHECK(!locked);
+ }
+
+ lock.unlock();
+ t.join();
+ }
+ catch(...)
+ {
+ lock.unlock();
+ t.join();
+ throw;
+ }
+ }
+
+
+ void operator()()
+ {
+ do_test(&this_type::locking_thread);
+ do_test(&this_type::locking_thread_through_constructor);
+ }
+};
+
template <typename M>
struct test_timedlock
{
@@ -109,6 +190,8 @@
void operator()()
{
+ test_lock_times_out_if_other_thread_has_lock<mutex_type>()();
+
mutex_type mutex;
boost::condition condition;
@@ -178,6 +261,7 @@
}
};
+
void do_test_mutex()
{
test_lock<boost::mutex>()();
Modified: branches/release/libs/thread/test/test_thread_move.cpp
==============================================================================
--- branches/release/libs/thread/test/test_thread_move.cpp (original)
+++ branches/release/libs/thread/test/test_thread_move.cpp 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -5,26 +5,59 @@
#include <boost/thread/thread.hpp>
#include <boost/test/unit_test.hpp>
-void do_nothing()
-{}
+void do_nothing(boost::thread::id* my_id)
+{
+ *my_id=boost::this_thread::get_id();
+}
void test_move_on_construction()
{
- boost::thread x=boost::thread(do_nothing);
+ boost::thread::id the_id;
+ boost::thread x=boost::thread(do_nothing,&the_id);
+ boost::thread::id x_id=x.get_id();
x.join();
+ BOOST_CHECK_EQUAL(the_id,x_id);
}
-boost::thread make_thread()
+boost::thread make_thread(boost::thread::id* the_id)
{
- return boost::thread(do_nothing);
+ return boost::thread(do_nothing,the_id);
}
void test_move_from_function_return()
{
- boost::thread x=make_thread();
+ boost::thread::id the_id;
+ boost::thread x=make_thread(&the_id);
+ boost::thread::id x_id=x.get_id();
x.join();
+ BOOST_CHECK_EQUAL(the_id,x_id);
+}
+
+boost::thread make_thread_return_lvalue(boost::thread::id* the_id)
+{
+ boost::thread t(do_nothing,the_id);
+ return boost::move(t);
}
+void test_move_from_function_return_lvalue()
+{
+ boost::thread::id the_id;
+ boost::thread x=make_thread_return_lvalue(&the_id);
+ boost::thread::id x_id=x.get_id();
+ x.join();
+ BOOST_CHECK_EQUAL(the_id,x_id);
+}
+
+void test_move_assign()
+{
+ boost::thread::id the_id;
+ boost::thread x(do_nothing,&the_id);
+ boost::thread y;
+ y=boost::move(x);
+ boost::thread::id y_id=y.get_id();
+ y.join();
+ BOOST_CHECK_EQUAL(the_id,y_id);
+}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
@@ -33,5 +66,7 @@
test->add(BOOST_TEST_CASE(test_move_on_construction));
test->add(BOOST_TEST_CASE(test_move_from_function_return));
+ test->add(BOOST_TEST_CASE(test_move_from_function_return_lvalue));
+ test->add(BOOST_TEST_CASE(test_move_assign));
return test;
}
Modified: branches/release/libs/thread/test/util.inl
==============================================================================
--- branches/release/libs/thread/test/util.inl (original)
+++ branches/release/libs/thread/test/util.inl 2008-10-13 16:30:13 EDT (Mon, 13 Oct 2008)
@@ -1,183 +1,183 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-// Copyright (C) 2007-8 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)
-
-#if !defined(UTIL_INL_WEK01242003)
-#define UTIL_INL_WEK01242003
-
-#include <boost/thread/xtime.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/condition.hpp>
-#include <boost/thread/thread.hpp>
-
-#ifndef DEFAULT_EXECUTION_MONITOR_TYPE
-# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition
-#endif
-
-// boostinspect:nounnamed
-
-namespace
-{
-inline boost::xtime delay(int secs, int msecs=0, int nsecs=0)
-{
- const int MILLISECONDS_PER_SECOND = 1000;
- const int NANOSECONDS_PER_SECOND = 1000000000;
- const int NANOSECONDS_PER_MILLISECOND = 1000000;
-
- boost::xtime xt;
- if (boost::TIME_UTC != boost::xtime_get (&xt, boost::TIME_UTC))
- BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC");
-
- nsecs += xt.nsec;
- msecs += nsecs / NANOSECONDS_PER_MILLISECOND;
- secs += msecs / MILLISECONDS_PER_SECOND;
- nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
- xt.nsec = nsecs % NANOSECONDS_PER_SECOND;
- xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND);
-
- return xt;
-}
-
-inline bool in_range(const boost::xtime& xt, int secs=1)
-{
- boost::xtime min = delay(-secs);
- boost::xtime max = delay(0);
- return (boost::xtime_cmp(xt, min) >= 0) &&
- (boost::xtime_cmp(xt, max) <= 0);
-}
-
-class execution_monitor
-{
-public:
- enum wait_type { use_sleep_only, use_mutex, use_condition };
-
- execution_monitor(wait_type type, int secs)
- : done(false), type(type), secs(secs) { }
- void start()
- {
- if (type != use_sleep_only) {
- boost::mutex::scoped_lock lock(mutex); done = false;
- } else {
- done = false;
- }
- }
- void finish()
- {
- if (type != use_sleep_only) {
- boost::mutex::scoped_lock lock(mutex);
- done = true;
- if (type == use_condition)
- cond.notify_one();
- } else {
- done = true;
- }
- }
- bool wait()
- {
- boost::xtime xt = delay(secs);
- if (type != use_condition)
- boost::thread::sleep(xt);
- if (type != use_sleep_only) {
- boost::mutex::scoped_lock lock(mutex);
- while (type == use_condition && !done) {
- if (!cond.timed_wait(lock, xt))
- break;
- }
- return done;
- }
- return done;
- }
-
-private:
- boost::mutex mutex;
- boost::condition cond;
- bool done;
- wait_type type;
- int secs;
-};
-
-template <typename F>
-class indirect_adapter
-{
-public:
- indirect_adapter(F func, execution_monitor& monitor)
- : func(func), monitor(monitor) { }
- void operator()() const
- {
- try
- {
- boost::thread thrd(func);
- thrd.join();
- }
- catch (...)
- {
- monitor.finish();
- throw;
- }
- monitor.finish();
- }
-
-private:
- F func;
- execution_monitor& monitor;
- void operator=(indirect_adapter&);
-};
-
-template <typename F>
-void timed_test(F func, int secs,
- execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE)
-{
- execution_monitor monitor(type, secs);
- indirect_adapter<F> ifunc(func, monitor);
- monitor.start();
- boost::thread thrd(ifunc);
- BOOST_REQUIRE_MESSAGE(monitor.wait(),
- "Timed test didn't complete in time, possible deadlock.");
-}
-
-template <typename F, typename T>
-class thread_binder
-{
-public:
- thread_binder(const F& func, const T& param)
- : func(func), param(param) { }
- void operator()() const { func(param); }
-
-private:
- F func;
- T param;
-};
-
-template <typename F, typename T>
-thread_binder<F, T> bind(const F& func, const T& param)
-{
- return thread_binder<F, T>(func, param);
-}
-
-template <typename R, typename T>
-class thread_member_binder
-{
-public:
- thread_member_binder(R (T::*func)(), T& param)
- : func(func), param(param) { }
- void operator()() const { (param.*func)(); }
-
-private:
- void operator=(thread_member_binder&);
-
- R (T::*func)();
- T& param;
-};
-
-
-template <typename R, typename T>
-thread_member_binder<R, T> bind(R (T::*func)(), T& param)
-{
- return thread_member_binder<R, T>(func, param);
-}
-} // namespace
-
-#endif
+// Copyright (C) 2001-2003
+// William E. Kempf
+// Copyright (C) 2007-8 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)
+
+#if !defined(UTIL_INL_WEK01242003)
+#define UTIL_INL_WEK01242003
+
+#include <boost/thread/xtime.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/thread.hpp>
+
+#ifndef DEFAULT_EXECUTION_MONITOR_TYPE
+# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition
+#endif
+
+// boostinspect:nounnamed
+
+namespace
+{
+inline boost::xtime delay(int secs, int msecs=0, int nsecs=0)
+{
+ const int MILLISECONDS_PER_SECOND = 1000;
+ const int NANOSECONDS_PER_SECOND = 1000000000;
+ const int NANOSECONDS_PER_MILLISECOND = 1000000;
+
+ boost::xtime xt;
+ if (boost::TIME_UTC != boost::xtime_get (&xt, boost::TIME_UTC))
+ BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC");
+
+ nsecs += xt.nsec;
+ msecs += nsecs / NANOSECONDS_PER_MILLISECOND;
+ secs += msecs / MILLISECONDS_PER_SECOND;
+ nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
+ xt.nsec = nsecs % NANOSECONDS_PER_SECOND;
+ xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND);
+
+ return xt;
+}
+
+inline bool in_range(const boost::xtime& xt, int secs=1)
+{
+ boost::xtime min = delay(-secs);
+ boost::xtime max = delay(0);
+ return (boost::xtime_cmp(xt, min) >= 0) &&
+ (boost::xtime_cmp(xt, max) <= 0);
+}
+
+class execution_monitor
+{
+public:
+ enum wait_type { use_sleep_only, use_mutex, use_condition };
+
+ execution_monitor(wait_type type, int secs)
+ : done(false), type(type), secs(secs) { }
+ void start()
+ {
+ if (type != use_sleep_only) {
+ boost::mutex::scoped_lock lock(mutex); done = false;
+ } else {
+ done = false;
+ }
+ }
+ void finish()
+ {
+ if (type != use_sleep_only) {
+ boost::mutex::scoped_lock lock(mutex);
+ done = true;
+ if (type == use_condition)
+ cond.notify_one();
+ } else {
+ done = true;
+ }
+ }
+ bool wait()
+ {
+ boost::xtime xt = delay(secs);
+ if (type != use_condition)
+ boost::thread::sleep(xt);
+ if (type != use_sleep_only) {
+ boost::mutex::scoped_lock lock(mutex);
+ while (type == use_condition && !done) {
+ if (!cond.timed_wait(lock, xt))
+ break;
+ }
+ return done;
+ }
+ return done;
+ }
+
+private:
+ boost::mutex mutex;
+ boost::condition cond;
+ bool done;
+ wait_type type;
+ int secs;
+};
+
+template <typename F>
+class indirect_adapter
+{
+public:
+ indirect_adapter(F func, execution_monitor& monitor)
+ : func(func), monitor(monitor) { }
+ void operator()() const
+ {
+ try
+ {
+ boost::thread thrd(func);
+ thrd.join();
+ }
+ catch (...)
+ {
+ monitor.finish();
+ throw;
+ }
+ monitor.finish();
+ }
+
+private:
+ F func;
+ execution_monitor& monitor;
+ void operator=(indirect_adapter&);
+};
+
+template <typename F>
+void timed_test(F func, int secs,
+ execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE)
+{
+ execution_monitor monitor(type, secs);
+ indirect_adapter<F> ifunc(func, monitor);
+ monitor.start();
+ boost::thread thrd(ifunc);
+ BOOST_REQUIRE_MESSAGE(monitor.wait(),
+ "Timed test didn't complete in time, possible deadlock.");
+}
+
+template <typename F, typename T>
+class thread_binder
+{
+public:
+ thread_binder(const F& func, const T& param)
+ : func(func), param(param) { }
+ void operator()() const { func(param); }
+
+private:
+ F func;
+ T param;
+};
+
+template <typename F, typename T>
+thread_binder<F, T> bind(const F& func, const T& param)
+{
+ return thread_binder<F, T>(func, param);
+}
+
+template <typename R, typename T>
+class thread_member_binder
+{
+public:
+ thread_member_binder(R (T::*func)(), T& param)
+ : func(func), param(param) { }
+ void operator()() const { (param.*func)(); }
+
+private:
+ void operator=(thread_member_binder&);
+
+ R (T::*func)();
+ T& param;
+};
+
+
+template <typename R, typename T>
+thread_member_binder<R, T> bind(R (T::*func)(), T& param)
+{
+ return thread_member_binder<R, T>(func, param);
+}
+} // namespace
+
+#endif
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