Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r56880 - in sandbox/task: boost/task libs/task/test
From: oliver.kowalke_at_[hidden]
Date: 2009-10-15 15:48:41


Author: olli
Date: 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
New Revision: 56880
URL: http://svn.boost.org/trac/boost/changeset/56880

Log:
- additiona unit-tests for spin-objects added -> from boost.thread

Added:
   sandbox/task/libs/task/test/condition_test_common.hpp (contents, props changed)
   sandbox/task/libs/task/test/test_generic_locks.cpp (contents, props changed)
   sandbox/task/libs/task/test/test_spin_condition_notify_all.cpp (contents, props changed)
   sandbox/task/libs/task/test/test_spin_condition_notify_one.cpp (contents, props changed)
   sandbox/task/libs/task/test/test_spin_condition_timed_wait_times_out.cpp (contents, props changed)
   sandbox/task/libs/task/test/util.ipp (contents, props changed)
Text files modified:
   sandbox/task/boost/task/spin_mutex.hpp | 4
   sandbox/task/libs/task/test/Jamfile.v2 | 4
   sandbox/task/libs/task/test/test_spin_condition.cpp | 234 +++++++++++++++++++--------------------
   sandbox/task/libs/task/test/test_spin_mutex.cpp | 66 +++++++---
   4 files changed, 164 insertions(+), 144 deletions(-)

Modified: sandbox/task/boost/task/spin_mutex.hpp
==============================================================================
--- sandbox/task/boost/task/spin_mutex.hpp (original)
+++ sandbox/task/boost/task/spin_mutex.hpp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -24,7 +24,7 @@
         volatile uint32_t state_;
 
 public:
- typedef spin_unique_lock< spin_mutex > scoped_lock;
+ typedef spin_unique_lock< spin_mutex > scoped_lock;
 
         spin_mutex();
 
@@ -41,6 +41,8 @@
         void unlock();
 };
 
+typedef spin_mutex spin_try_mutex;
+
 }}
 
 #endif // BOOST_TASK_SPIN_MUTEX_H

Modified: sandbox/task/libs/task/test/Jamfile.v2
==============================================================================
--- sandbox/task/libs/task/test/Jamfile.v2 (original)
+++ sandbox/task/libs/task/test/Jamfile.v2 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -37,7 +37,11 @@
     [ task-test test_semaphore ]
     [ task-test test_spin_mutex ]
     [ task-test test_spin_unique_lock ]
+ [ task-test test_generic_locks ]
     [ task-test test_spin_condition ]
+ [ task-test test_spin_condition_notify_all ]
+ [ task-test test_spin_condition_notify_one ]
+ [ task-test test_spin_condition_timed_wait_times_out ]
     [ task-test test_spin_count_down_event ]
     [ task-test test_spin_auto_reset_event ]
     [ task-test test_spin_manual_reset_event ]

Added: sandbox/task/libs/task/test/condition_test_common.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/condition_test_common.hpp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -0,0 +1,99 @@
+#ifndef TASK_CONDITION_TEST_COMMON_HPP
+#define TASK_CONDITION_TEST_COMMON_HPP
+// Copyright (C) 2007 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/utility.hpp>
+#include <boost/thread/thread_time.hpp>
+
+#include <boost/task.hpp>
+
+namespace tsk = boost::task;
+
+unsigned const timeout_seconds=5;
+
+struct wait_for_flag : private boost::noncopyable
+{
+ tsk::spin_mutex mutex;
+ tsk::spin_condition cond_var;
+ bool flag;
+ unsigned woken;
+
+ wait_for_flag():
+ flag(false),woken(0)
+ {}
+
+ struct check_flag
+ {
+ bool const& flag;
+
+ check_flag(bool const& flag_):
+ flag(flag_)
+ {}
+
+ bool operator()() const
+ {
+ return flag;
+ }
+ private:
+ void operator=(check_flag&);
+ };
+
+
+ void wait_without_predicate()
+ {
+ tsk::spin_mutex::scoped_lock lock(mutex);
+ while(!flag)
+ {
+ cond_var.wait(lock);
+ }
+ ++woken;
+ }
+
+ void wait_with_predicate()
+ {
+ tsk::spin_mutex::scoped_lock lock(mutex);
+ cond_var.wait(lock,check_flag(flag));
+ if(flag)
+ {
+ ++woken;
+ }
+ }
+
+ void timed_wait_without_predicate()
+ {
+ boost::system_time const timeout=boost::get_system_time()+boost::posix_time::seconds(timeout_seconds);
+
+ tsk::spin_mutex::scoped_lock lock(mutex);
+ while(!flag)
+ {
+ if(!cond_var.timed_wait(lock,timeout))
+ {
+ return;
+ }
+ }
+ ++woken;
+ }
+
+ void timed_wait_with_predicate()
+ {
+ boost::system_time const timeout=boost::get_system_time()+boost::posix_time::seconds(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(mutex);
+ if(cond_var.timed_wait(lock,timeout,check_flag(flag)) && flag)
+ {
+ ++woken;
+ }
+ }
+ void relative_timed_wait_with_predicate()
+ {
+ tsk::spin_mutex::scoped_lock lock(mutex);
+ if(cond_var.timed_wait(lock,boost::posix_time::seconds(timeout_seconds),check_flag(flag)) && flag)
+ {
+ ++woken;
+ }
+ }
+};
+
+#endif

Added: sandbox/task/libs/task/test/test_generic_locks.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_generic_locks.cpp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -0,0 +1,524 @@
+// (C) Copyright 2008 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.hpp>
+#include <boost/task.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+namespace tsk = boost::task;
+
+void test_lock_two_uncontended()
+{
+ tsk::spin_mutex m1,m2;
+
+ tsk::spin_mutex::scoped_lock l1(m1,boost::defer_lock),
+ l2(m2,boost::defer_lock);
+
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+
+ boost::lock(l1,l2);
+
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+}
+
+struct wait_data
+{
+ tsk::spin_mutex m;
+ bool flag;
+ tsk::spin_condition cond;
+
+ wait_data():
+ flag(false)
+ {}
+
+ void wait()
+ {
+ tsk::spin_mutex::scoped_lock l(m);
+ while(!flag)
+ {
+ cond.wait(l);
+ }
+ }
+
+ template<typename Duration>
+ bool timed_wait(Duration d)
+ {
+ boost::system_time const target=boost::get_system_time()+d;
+
+ tsk::spin_mutex::scoped_lock l(m);
+ while(!flag)
+ {
+ if(!cond.timed_wait(l,target))
+ {
+ return flag;
+ }
+ }
+ return true;
+ }
+
+ void signal()
+ {
+ tsk::spin_mutex::scoped_lock l(m);
+ flag=true;
+ cond.notify_all();
+ }
+};
+
+
+void lock_mutexes_slowly(tsk::spin_mutex* m1,tsk::spin_mutex* m2,wait_data* locked,wait_data* quit)
+{
+ boost::lock_guard<tsk::spin_mutex> l1(*m1);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<tsk::spin_mutex> l2(*m2);
+ locked->signal();
+ quit->wait();
+}
+
+void lock_pair(tsk::spin_mutex* m1,tsk::spin_mutex* m2)
+{
+ boost::lock(*m1,*m2);
+ tsk::spin_mutex::scoped_lock l1(*m1,boost::adopt_lock),
+ l2(*m2,boost::adopt_lock);
+}
+
+void test_lock_two_other_thread_locks_in_order()
+{
+ tsk::spin_mutex m1,m2;
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_pair,&m1,&m2);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1)));
+
+ t.join();
+}
+
+void test_lock_two_other_thread_locks_in_opposite_order()
+{
+ tsk::spin_mutex m1,m2;
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_pair,&m2,&m1);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1)));
+
+ t.join();
+}
+
+void test_lock_five_uncontended()
+{
+ tsk::spin_mutex m1,m2,m3,m4,m5;
+
+ tsk::spin_mutex::scoped_lock l1(m1,boost::defer_lock),
+ l2(m2,boost::defer_lock),
+ l3(m3,boost::defer_lock),
+ l4(m4,boost::defer_lock),
+ l5(m5,boost::defer_lock);
+
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+ BOOST_CHECK(!l3.owns_lock());
+ BOOST_CHECK(!l4.owns_lock());
+ BOOST_CHECK(!l5.owns_lock());
+
+ boost::lock(l1,l2,l3,l4,l5);
+
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+ BOOST_CHECK(l3.owns_lock());
+ BOOST_CHECK(l4.owns_lock());
+ BOOST_CHECK(l5.owns_lock());
+}
+
+void lock_five_mutexes_slowly(tsk::spin_mutex* m1,tsk::spin_mutex* m2,tsk::spin_mutex* m3,tsk::spin_mutex* m4,tsk::spin_mutex* m5,
+ wait_data* locked,wait_data* quit)
+{
+ boost::lock_guard<tsk::spin_mutex> l1(*m1);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<tsk::spin_mutex> l2(*m2);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<tsk::spin_mutex> l3(*m3);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<tsk::spin_mutex> l4(*m4);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<tsk::spin_mutex> l5(*m5);
+ locked->signal();
+ quit->wait();
+}
+
+void lock_five(tsk::spin_mutex* m1,tsk::spin_mutex* m2,tsk::spin_mutex* m3,tsk::spin_mutex* m4,tsk::spin_mutex* m5)
+{
+ boost::lock(*m1,*m2,*m3,*m4,*m5);
+ m1->unlock();
+ m2->unlock();
+ m3->unlock();
+ m4->unlock();
+ m5->unlock();
+}
+
+void test_lock_five_other_thread_locks_in_order()
+{
+ tsk::spin_mutex m1,m2,m3,m4,m5;
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_five,&m1,&m2,&m3,&m4,&m5);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));
+
+ t.join();
+}
+
+void test_lock_five_other_thread_locks_in_different_order()
+{
+ tsk::spin_mutex m1,m2,m3,m4,m5;
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_five,&m5,&m1,&m4,&m2,&m3);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));
+
+ t.join();
+}
+
+void lock_n(tsk::spin_mutex* mutexes,unsigned count)
+{
+ boost::lock(mutexes,mutexes+count);
+ for(unsigned i=0;i<count;++i)
+ {
+ mutexes[i].unlock();
+ }
+}
+
+
+void test_lock_ten_other_thread_locks_in_different_order()
+{
+ unsigned const num_mutexes=10;
+
+ tsk::spin_mutex mutexes[num_mutexes];
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_five_mutexes_slowly,&mutexes[6],&mutexes[3],&mutexes[8],&mutexes[0],&mutexes[2],&locked,&release);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_n,mutexes,num_mutexes);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));
+
+ t.join();
+}
+
+struct dummy_mutex
+{
+ bool is_locked;
+
+ dummy_mutex():
+ is_locked(false)
+ {}
+
+ void lock()
+ {
+ is_locked=true;
+ }
+
+ bool try_lock()
+ {
+ if(is_locked)
+ {
+ return false;
+ }
+ is_locked=true;
+ return true;
+ }
+
+ void unlock()
+ {
+ is_locked=false;
+ }
+};
+
+namespace boost
+{
+ template<>
+ struct is_mutex_type<dummy_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+}
+
+
+
+void test_lock_five_in_range()
+{
+ unsigned const num_mutexes=5;
+ dummy_mutex mutexes[num_mutexes];
+
+ boost::lock(mutexes,mutexes+num_mutexes);
+
+ for(unsigned i=0;i<num_mutexes;++i)
+ {
+ BOOST_CHECK(mutexes[i].is_locked);
+ }
+}
+
+void test_lock_ten_in_range()
+{
+ unsigned const num_mutexes=10;
+ dummy_mutex mutexes[num_mutexes];
+
+ boost::lock(mutexes,mutexes+num_mutexes);
+
+ for(unsigned i=0;i<num_mutexes;++i)
+ {
+ BOOST_CHECK(mutexes[i].is_locked);
+ }
+}
+
+void test_try_lock_two_uncontended()
+{
+ dummy_mutex m1,m2;
+
+ int const res=boost::try_lock(m1,m2);
+
+ BOOST_CHECK(res==-1);
+ BOOST_CHECK(m1.is_locked);
+ BOOST_CHECK(m2.is_locked);
+}
+void test_try_lock_two_first_locked()
+{
+ dummy_mutex m1,m2;
+ m1.lock();
+
+ boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock),
+ l2(m2,boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2);
+
+ BOOST_CHECK(res==0);
+ BOOST_CHECK(m1.is_locked);
+ BOOST_CHECK(!m2.is_locked);
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+}
+void test_try_lock_two_second_locked()
+{
+ dummy_mutex m1,m2;
+ m2.lock();
+
+ boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock),
+ l2(m2,boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2);
+
+ BOOST_CHECK(res==1);
+ BOOST_CHECK(!m1.is_locked);
+ BOOST_CHECK(m2.is_locked);
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+}
+
+void test_try_lock_three()
+{
+ int const num_mutexes=3;
+
+ for(int i=-1;i<num_mutexes;++i)
+ {
+ dummy_mutex mutexes[num_mutexes];
+
+ if(i>=0)
+ {
+ mutexes[i].lock();
+ }
+ boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),
+ l2(mutexes[1],boost::defer_lock),
+ l3(mutexes[2],boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2,l3);
+
+ BOOST_CHECK(res==i);
+ for(int j=0;j<num_mutexes;++j)
+ {
+ if((i==j) || (i==-1))
+ {
+ BOOST_CHECK(mutexes[j].is_locked);
+ }
+ else
+ {
+ BOOST_CHECK(!mutexes[j].is_locked);
+ }
+ }
+ if(i==-1)
+ {
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+ BOOST_CHECK(l3.owns_lock());
+ }
+ else
+ {
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+ BOOST_CHECK(!l3.owns_lock());
+ }
+ }
+}
+
+void test_try_lock_four()
+{
+ int const num_mutexes=4;
+
+ for(int i=-1;i<num_mutexes;++i)
+ {
+ dummy_mutex mutexes[num_mutexes];
+
+ if(i>=0)
+ {
+ mutexes[i].lock();
+ }
+ boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),
+ l2(mutexes[1],boost::defer_lock),
+ l3(mutexes[2],boost::defer_lock),
+ l4(mutexes[3],boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2,l3,l4);
+
+ BOOST_CHECK(res==i);
+ for(int j=0;j<num_mutexes;++j)
+ {
+ if((i==j) || (i==-1))
+ {
+ BOOST_CHECK(mutexes[j].is_locked);
+ }
+ else
+ {
+ BOOST_CHECK(!mutexes[j].is_locked);
+ }
+ }
+ if(i==-1)
+ {
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+ BOOST_CHECK(l3.owns_lock());
+ BOOST_CHECK(l4.owns_lock());
+ }
+ else
+ {
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+ BOOST_CHECK(!l3.owns_lock());
+ BOOST_CHECK(!l4.owns_lock());
+ }
+ }
+}
+
+void test_try_lock_five()
+{
+ int const num_mutexes=5;
+
+ for(int i=-1;i<num_mutexes;++i)
+ {
+ dummy_mutex mutexes[num_mutexes];
+
+ if(i>=0)
+ {
+ mutexes[i].lock();
+ }
+ boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),
+ l2(mutexes[1],boost::defer_lock),
+ l3(mutexes[2],boost::defer_lock),
+ l4(mutexes[3],boost::defer_lock),
+ l5(mutexes[4],boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2,l3,l4,l5);
+
+ BOOST_CHECK(res==i);
+ for(int j=0;j<num_mutexes;++j)
+ {
+ if((i==j) || (i==-1))
+ {
+ BOOST_CHECK(mutexes[j].is_locked);
+ }
+ else
+ {
+ BOOST_CHECK(!mutexes[j].is_locked);
+ }
+ }
+ if(i==-1)
+ {
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+ BOOST_CHECK(l3.owns_lock());
+ BOOST_CHECK(l4.owns_lock());
+ BOOST_CHECK(l5.owns_lock());
+ }
+ else
+ {
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+ BOOST_CHECK(!l3.owns_lock());
+ BOOST_CHECK(!l4.owns_lock());
+ BOOST_CHECK(!l5.owns_lock());
+ }
+ }
+}
+
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Task: generic locks test suite");
+
+ test->add(BOOST_TEST_CASE(&test_lock_two_uncontended));
+ test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_order));
+ test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_opposite_order));
+ test->add(BOOST_TEST_CASE(&test_lock_five_uncontended));
+ test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));
+ test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));
+ test->add(BOOST_TEST_CASE(&test_lock_five_in_range));
+ test->add(BOOST_TEST_CASE(&test_lock_ten_in_range));
+ test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));
+ test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));
+ test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));
+ test->add(BOOST_TEST_CASE(&test_try_lock_two_second_locked));
+ test->add(BOOST_TEST_CASE(&test_try_lock_three));
+ test->add(BOOST_TEST_CASE(&test_try_lock_four));
+ test->add(BOOST_TEST_CASE(&test_try_lock_five));
+
+ return test;
+}

Modified: sandbox/task/libs/task/test/test_spin_condition.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_spin_condition.cpp (original)
+++ sandbox/task/libs/task/test/test_spin_condition.cpp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -1,201 +1,191 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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)
+// Copyright (C) 2001-2003
+// William E. Kempf
+// Copyright (C) 2007 Anthony Williams
 //
-// This test is based on the tests of Boost.Thread
-
-#include <cstdlib>
-#include <iostream>
-#include <map>
-#include <stdexcept>
-#include <vector>
+// 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/bind.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/function.hpp>
-#include <boost/ref.hpp>
-#include <boost/test/unit_test.hpp>
 #include <boost/thread.hpp>
-#include <boost/utility.hpp>
-
 #include <boost/task.hpp>
 
-namespace pt = boost::posix_time;
-namespace tsk = boost::task;
+#include <boost/test/unit_test.hpp>
 
-namespace {
+#include <libs/task/test/util.ipp>
 
-struct condition_test
+namespace tsk = boost::task;
+namespace pt = boost::posix_time;
+
+struct condition_test_data
 {
- condition_test() :
- notified( 0),
- awoken( 0)
- {}
+ condition_test_data() : notified(0), awoken(0) { }
 
- tsk::spin_mutex mtx;
- tsk::spin_condition condition;
+ tsk::spin_mutex mutex;
+ tsk::spin_condition condition;
     int notified;
     int awoken;
 };
 
-struct cond_predicate
+void condition_test_thread(condition_test_data* data)
 {
- cond_predicate( int & var_, int val_) :
- var( var_),
- val( val_)
- {}
+ tsk::spin_mutex::scoped_lock lock(data->mutex);
+ BOOST_CHECK(lock ? true : false);
+ while (!(data->notified > 0))
+ data->condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ data->awoken++;
+}
 
- bool operator()()
- { return var == val; }
+struct cond_predicate
+{
+ cond_predicate(int& var, int val) : _var(var), _val(val) { }
 
- int & var;
- int val;
+ bool operator()() { return _var == _val; }
 
+ int& _var;
+ int _val;
 private:
- void operator=( cond_predicate&);
+ void operator=(cond_predicate&);
+
 };
 
-void condition_test_thread( condition_test * data)
-{
- tsk::spin_mutex::scoped_lock lk( data->mtx);
- BOOST_CHECK( lk);
- while ( ! ( data->notified > 0) )
- data->condition.wait( lk);
- BOOST_CHECK( lk);
- data->awoken++;
-}
-
-void condition_test_waits( condition_test * data)
+void condition_test_waits(condition_test_data* data)
 {
- tsk::spin_mutex::scoped_lock lk( data->mtx);
- BOOST_CHECK( lk);
+ tsk::spin_mutex::scoped_lock lock(data->mutex);
+ BOOST_CHECK(lock ? true : false);
 
     // Test wait.
- while ( data->notified != 1)
- data->condition.wait( lk);
- BOOST_CHECK( lk);
- BOOST_CHECK_EQUAL( data->notified, 1);
+ while (data->notified != 1)
+ data->condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data->notified, 1);
     data->awoken++;
     data->condition.notify_one();
 
     // Test predicate wait.
- data->condition.wait( lk, cond_predicate( data->notified, 2));
- BOOST_CHECK( lk);
- BOOST_CHECK_EQUAL( data->notified, 2);
+ data->condition.wait(lock, cond_predicate(data->notified, 2));
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data->notified, 2);
     data->awoken++;
     data->condition.notify_one();
 
     // Test timed_wait.
- pt::millisec xt( 250);
- while ( data->notified != 3)
- data->condition.timed_wait( lk, xt);
- BOOST_CHECK( lk);
- BOOST_CHECK_EQUAL( data->notified, 3);
+ pt::time_duration xt = pt::seconds(10);
+ while (data->notified != 3)
+ data->condition.timed_wait(lock, xt);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data->notified, 3);
     data->awoken++;
     data->condition.notify_one();
 
     // Test predicate timed_wait.
- cond_predicate pred( data->notified, 4);
- BOOST_CHECK( data->condition.timed_wait( lk, xt, pred));
- BOOST_CHECK( lk);
- BOOST_CHECK( pred() );
- BOOST_CHECK_EQUAL( data->notified, 4);
+ xt = pt::seconds(10);
+ cond_predicate pred(data->notified, 4);
+ BOOST_CHECK(data->condition.timed_wait(lock, xt, pred));
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK(pred());
+ BOOST_CHECK_EQUAL(data->notified, 4);
     data->awoken++;
     data->condition.notify_one();
 
     // Test predicate timed_wait with relative timeout
- cond_predicate pred_rel( data->notified, 5);
- BOOST_CHECK( data->condition.timed_wait( lk, pt::seconds( 10), pred_rel) );
- BOOST_CHECK( lk);
- BOOST_CHECK( pred_rel() );
- BOOST_CHECK_EQUAL( data->notified, 5);
+ cond_predicate pred_rel(data->notified, 5);
+ BOOST_CHECK(data->condition.timed_wait(lock, boost::posix_time::seconds(10), pred_rel));
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK(pred_rel());
+ BOOST_CHECK_EQUAL(data->notified, 5);
     data->awoken++;
     data->condition.notify_one();
 }
 
-void test_wait()
+void do_test_condition_waits()
 {
- condition_test data;
+ condition_test_data data;
 
- boost::thread thrd(
- boost::bind(
- & condition_test_waits, & data) );
+ boost::thread thread(bind(&condition_test_waits, &data));
 
     {
- tsk::spin_mutex::scoped_lock lk( data.mtx);
- BOOST_CHECK( lk);
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ BOOST_CHECK(lock ? true : false);
 
- boost::this_thread::sleep( pt::millisec( 250) );
+ boost::this_thread::sleep(pt::seconds(1));
         data.notified++;
         data.condition.notify_one();
- while ( data.awoken != 1)
- data.condition.wait( lk);
- BOOST_CHECK( lk);
- BOOST_CHECK_EQUAL( data.awoken, 1);
+ while (data.awoken != 1)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 1);
 
- boost::this_thread::sleep( pt::millisec( 250) );
+ boost::this_thread::sleep(pt::seconds(1));
         data.notified++;
         data.condition.notify_one();
- while ( data.awoken != 2)
- data.condition.wait( lk);
- BOOST_CHECK( lk);
- BOOST_CHECK_EQUAL( data.awoken, 2);
+ while (data.awoken != 2)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 2);
 
- boost::this_thread::sleep( pt::millisec( 250) );
+ boost::this_thread::sleep(pt::seconds(1));
         data.notified++;
         data.condition.notify_one();
- while ( data.awoken != 3)
- data.condition.wait( lk);
- BOOST_CHECK( lk);
- BOOST_CHECK_EQUAL( data.awoken, 3);
+ while (data.awoken != 3)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 3);
 
- boost::this_thread::sleep( pt::millisec( 250) );
+ boost::this_thread::sleep(pt::seconds(1));
         data.notified++;
         data.condition.notify_one();
- while ( data.awoken != 4)
- data.condition.wait( lk);
- BOOST_CHECK( lk);
- BOOST_CHECK_EQUAL( data.awoken, 4);
+ while (data.awoken != 4)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 4);
 
- boost::this_thread::sleep( pt::millisec( 250) );
+
+ boost::this_thread::sleep(pt::seconds(1));
         data.notified++;
         data.condition.notify_one();
- while ( data.awoken != 5)
- data.condition.wait( lk);
- BOOST_CHECK( lk);
- BOOST_CHECK_EQUAL( data.awoken, 5);
+ while (data.awoken != 5)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 5);
     }
 
- thrd.join();
- BOOST_CHECK_EQUAL( data.awoken, 5);
+ thread.join();
+ BOOST_CHECK_EQUAL(data.awoken, 5);
 }
 
-
-void test_interruption_point()
+void test_condition_waits()
 {
- condition_test data;
+ // We should have already tested notify_one here, so
+ // a timed test with the default execution_monitor::use_condition
+ // should be OK, and gives the fastest performance
+ timed_test(&do_test_condition_waits, 12);
+}
 
- boost::thread thrd(
- boost::bind(
- & condition_test_thread, & data) );
+void do_test_condition_wait_is_a_interruption_point()
+{
+ condition_test_data data;
 
- thrd.interrupt();
- thrd.join();
+ boost::thread thread(bind(&condition_test_thread, &data));
 
- BOOST_CHECK_EQUAL( data.awoken, 0);
+ thread.interrupt();
+ thread.join();
+ BOOST_CHECK_EQUAL(data.awoken,0);
 }
 
+
+void test_condition_wait_is_a_interruption_point()
+{
+ timed_test(&do_test_condition_wait_is_a_interruption_point, 1);
 }
 
-boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
 {
- boost::unit_test_framework::test_suite * test =
- BOOST_TEST_SUITE("Boost.Task: spin-condition test suite");
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Task: condition test suite");
 
- test->add( BOOST_TEST_CASE( & test_wait) );
- test->add( BOOST_TEST_CASE( & test_interruption_point) );
+ test->add(BOOST_TEST_CASE(&test_condition_waits));
+ test->add(BOOST_TEST_CASE(&test_condition_wait_is_a_interruption_point));
 
- return test;
+ return test;
 }

Added: sandbox/task/libs/task/test/test_spin_condition_notify_all.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_spin_condition_notify_all.cpp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -0,0 +1,225 @@
+// Copyright (C) 2007 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/task.hpp>
+
+#include <libs/task/test/util.ipp>
+
+#include "condition_test_common.hpp"
+
+namespace tsk = boost::task;
+
+unsigned const number_of_test_threads=5;
+
+void do_test_condition_notify_all_wakes_from_wait()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(boost::bind(&wait_for_flag::wait_without_predicate, boost::ref( data)));
+ }
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+void do_test_condition_notify_all_wakes_from_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(boost::bind(&wait_for_flag::wait_with_predicate, boost::ref( data)));
+ }
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+void do_test_condition_notify_all_wakes_from_timed_wait()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(boost::bind(&wait_for_flag::timed_wait_without_predicate, boost::ref( data)));
+ }
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+void do_test_condition_notify_all_wakes_from_timed_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(boost::bind(&wait_for_flag::timed_wait_with_predicate, boost::ref( data)));
+ }
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+void do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(boost::bind(&wait_for_flag::relative_timed_wait_with_predicate, boost::ref( data)));
+ }
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+namespace
+{
+ tsk::spin_mutex multiple_wake_mutex;
+ tsk::spin_condition multiple_wake_cond;
+ unsigned multiple_wake_count=0;
+
+ void wait_for_condvar_and_increase_count()
+ {
+ tsk::spin_mutex::scoped_lock lk(multiple_wake_mutex);
+ multiple_wake_cond.wait(lk);
+ ++multiple_wake_count;
+ }
+}
+
+
+void do_test_notify_all_following_notify_one_wakes_all_threads()
+{
+ boost::thread thread1(wait_for_condvar_and_increase_count);
+ boost::thread thread2(wait_for_condvar_and_increase_count);
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ multiple_wake_cond.notify_one();
+
+ boost::thread thread3(wait_for_condvar_and_increase_count);
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ multiple_wake_cond.notify_one();
+ multiple_wake_cond.notify_all();
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+
+ {
+ tsk::spin_mutex::scoped_lock lk(multiple_wake_mutex);
+ BOOST_CHECK(multiple_wake_count==3);
+ }
+
+ thread1.join();
+ thread2.join();
+ thread3.join();
+}
+
+void test_condition_notify_all()
+{
+ timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds);
+ timed_test(&do_test_condition_notify_all_wakes_from_wait_with_predicate, timeout_seconds);
+ timed_test(&do_test_condition_notify_all_wakes_from_timed_wait, timeout_seconds);
+ timed_test(&do_test_condition_notify_all_wakes_from_timed_wait_with_predicate, timeout_seconds);
+ timed_test(&do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate, timeout_seconds);
+ timed_test(&do_test_notify_all_following_notify_one_wakes_all_threads, timeout_seconds);
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Task: condition test suite");
+
+ test->add(BOOST_TEST_CASE(&test_condition_notify_all));
+
+ return test;
+}

Added: sandbox/task/libs/task/test/test_spin_condition_notify_one.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_spin_condition_notify_one.cpp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -0,0 +1,159 @@
+// Copyright (C) 2007 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/task.hpp>
+
+#include <libs/task/test/util.ipp>
+
+#include "condition_test_common.hpp"
+
+namespace tsk = boost::task;
+
+void do_test_condition_notify_one_wakes_from_wait()
+{
+ wait_for_flag data;
+
+ boost::thread thread(boost::bind(&wait_for_flag::wait_without_predicate, boost::ref(data)));
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+void do_test_condition_notify_one_wakes_from_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread thread(boost::bind(&wait_for_flag::wait_with_predicate, boost::ref(data)));
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+void do_test_condition_notify_one_wakes_from_timed_wait()
+{
+ wait_for_flag data;
+
+ boost::thread thread(boost::bind(&wait_for_flag::timed_wait_without_predicate, boost::ref(data)));
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+void do_test_condition_notify_one_wakes_from_timed_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread thread(boost::bind(&wait_for_flag::timed_wait_with_predicate, boost::ref(data)));
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+void do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread thread(boost::bind(&wait_for_flag::relative_timed_wait_with_predicate, boost::ref( data)));
+
+ {
+ tsk::spin_mutex::scoped_lock lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+namespace
+{
+ tsk::spin_mutex multiple_wake_mutex;
+ tsk::spin_condition multiple_wake_cond;
+ unsigned multiple_wake_count=0;
+
+ void wait_for_condvar_and_increase_count()
+ {
+ tsk::spin_mutex::scoped_lock lk(multiple_wake_mutex);
+ multiple_wake_cond.wait(lk);
+ ++multiple_wake_count;
+ }
+
+}
+
+
+void do_test_multiple_notify_one_calls_wakes_multiple_threads()
+{
+ boost::thread thread1(wait_for_condvar_and_increase_count);
+ boost::thread thread2(wait_for_condvar_and_increase_count);
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ multiple_wake_cond.notify_one();
+
+ boost::thread thread3(wait_for_condvar_and_increase_count);
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ multiple_wake_cond.notify_one();
+ multiple_wake_cond.notify_one();
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+
+ {
+ tsk::spin_mutex::scoped_lock lk(multiple_wake_mutex);
+ BOOST_CHECK(multiple_wake_count==3);
+ }
+
+ thread1.join();
+ thread2.join();
+ thread3.join();
+}
+
+void test_condition_notify_one()
+{
+ timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex);
+ timed_test(&do_test_condition_notify_one_wakes_from_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
+ timed_test(&do_test_condition_notify_one_wakes_from_timed_wait, timeout_seconds, execution_monitor::use_mutex);
+ timed_test(&do_test_condition_notify_one_wakes_from_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
+ timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
+ timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex);
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Task: condition test suite");
+
+ test->add(BOOST_TEST_CASE(&test_condition_notify_one));
+
+ return test;
+}

Added: sandbox/task/libs/task/test/test_spin_condition_timed_wait_times_out.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_spin_condition_timed_wait_times_out.cpp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -0,0 +1,175 @@
+// 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)
+
+#include <boost/thread.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/task.hpp>
+
+#include <libs/task/test/util.ipp>
+
+namespace tsk = boost::task;
+
+bool fake_predicate()
+{
+ return false;
+}
+
+unsigned const timeout_seconds=2;
+unsigned const timeout_grace=1;
+boost::posix_time::milliseconds const timeout_resolution(100);
+
+
+void do_test_timed_wait_times_out()
+{
+ tsk::spin_condition cond;
+ tsk::spin_mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+delay;
+
+ while(cond.timed_wait(lock,timeout));
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_timed_wait_with_predicate_times_out()
+{
+ tsk::spin_condition cond;
+ tsk::spin_mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+delay;
+
+ bool const res=cond.timed_wait(lock,timeout,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_relative_timed_wait_with_predicate_times_out()
+{
+ tsk::spin_condition cond;
+ tsk::spin_mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ bool const res=cond.timed_wait(lock,delay,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_timed_wait_relative_times_out()
+{
+ tsk::spin_condition cond;
+ tsk::spin_mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ while(cond.timed_wait(lock,delay));
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_cv_any_timed_wait_times_out()
+{
+ tsk::spin_condition cond;
+ tsk::spin_mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+delay;
+
+ while(cond.timed_wait(lock,timeout));
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_cv_any_timed_wait_with_predicate_times_out()
+{
+ tsk::spin_condition cond;
+ tsk::spin_mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+delay;
+
+ bool const res=cond.timed_wait(lock,timeout,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_cv_any_relative_timed_wait_with_predicate_times_out()
+{
+ tsk::spin_condition cond;
+ tsk::spin_mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ bool const res=cond.timed_wait(lock,delay,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+void do_test_cv_any_timed_wait_relative_times_out()
+{
+ tsk::spin_condition cond;
+ tsk::spin_mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ tsk::spin_mutex::scoped_lock lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ while(cond.timed_wait(lock,delay));
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+
+void test_timed_wait_times_out()
+{
+ timed_test(&do_test_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_cv_any_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_cv_any_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_cv_any_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+ timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Task: condition test suite");
+
+ test->add(BOOST_TEST_CASE(&test_timed_wait_times_out));
+
+ return test;
+}

Modified: sandbox/task/libs/task/test/test_spin_mutex.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_spin_mutex.cpp (original)
+++ sandbox/task/libs/task/test/test_spin_mutex.cpp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -22,40 +22,64 @@
 
 #include <boost/task.hpp>
 
+#include <libs/task/test/util.ipp>
+
 namespace pt = boost::posix_time;
 namespace tsk = boost::task;
 
-namespace {
-
-void test_lock()
+template< typename M >
+struct test_lock
 {
- tsk::spin_mutex mtx;
- tsk::spin_condition cond;
-
- {
- tsk::spin_mutex::scoped_lock lk( mtx);
- BOOST_CHECK( lk);
- }
- tsk::spin_mutex::scoped_lock lk( mtx);
- BOOST_CHECK( lk);
-
- BOOST_CHECK( ! cond.timed_wait( lk, pt::millisec( 250) ) );
- BOOST_CHECK( lk);
-
- lk.unlock();
- BOOST_CHECK( ! lk);
- lk.lock();
- BOOST_CHECK( lk);
+ typedef M mutex_type;
+ typedef typename M::scoped_lock lock_type;
+
+ void operator()()
+ {
+ mutex_type mutex;
+ tsk::spin_condition condition;
+
+ // Test the lock's constructors.
+ {
+ lock_type lock(mutex, boost::defer_lock);
+ BOOST_CHECK(!lock);
+ }
+ lock_type lock(mutex);
+ BOOST_CHECK(lock ? true : false);
+
+ // Construct and initialize an xtime for a fast time out.
+ pt::time_duration xt = pt::milliseconds( 100);
+
+ // Test the lock and the mutex with condition variables.
+ // No one is going to notify this condition variable. We expect to
+ // time out.
+ BOOST_CHECK(!condition.timed_wait(lock, xt));
+ BOOST_CHECK(lock ? true : false);
+
+ // Test the lock and unlock methods.
+ lock.unlock();
+ BOOST_CHECK(!lock);
+ lock.lock();
+ BOOST_CHECK(lock ? true : false);
+ }
 };
 
+void do_test_mutex()
+{
+ test_lock< tsk::spin_mutex >()();
+}
+
+void test_mutex()
+{
+ timed_test(&do_test_mutex, 3);
 }
 
+
 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
 {
     boost::unit_test_framework::test_suite * test =
                 BOOST_TEST_SUITE("Boost.Task: spin-mutex test suite");
 
- test->add( BOOST_TEST_CASE( & test_lock) );
+ test->add(BOOST_TEST_CASE(&test_mutex));
 
         return test;
 }

Added: sandbox/task/libs/task/test/util.ipp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/util.ipp 2009-10-15 15:48:40 EDT (Thu, 15 Oct 2009)
@@ -0,0 +1,160 @@
+// 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/date_time/posix_time/posix_time.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 pt = boost::posix_time;
+
+namespace
+{
+
+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()
+ {
+ pt::time_duration xt = pt::seconds(secs);
+ if (type != use_condition)
+ boost::this_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