$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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