Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r77003 - in trunk: boost/thread/pthread libs/thread/test libs/thread/test/sync/mutual_exclusion/shared_mutex
From: vicente.botet_at_[hidden]
Date: 2012-02-12 17:39:01


Author: viboes
Date: 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
New Revision: 77003
URL: http://svn.boost.org/trac/boost/changeset/77003

Log:
Thread: Added chrono i/f for shared_mutex pthread
Added:
   trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp (contents, props changed)
   trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp (contents, props changed)
   trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp (contents, props changed)
   trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp (contents, props changed)
   trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp (contents, props changed)
   trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp (contents, props changed)
   trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp (contents, props changed)
   trunk/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp (contents, props changed)
Text files modified:
   trunk/boost/thread/pthread/shared_mutex.hpp | 98 +++++++++++++++++++++++++++++++++++++++
   trunk/libs/thread/test/Jamfile.v2 | 11 ++++
   2 files changed, 107 insertions(+), 2 deletions(-)

Modified: trunk/boost/thread/pthread/shared_mutex.hpp
==============================================================================
--- trunk/boost/thread/pthread/shared_mutex.hpp (original)
+++ trunk/boost/thread/pthread/shared_mutex.hpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -12,6 +12,10 @@
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/condition_variable.hpp>
 #include <boost/thread/detail/thread_interruption.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
 
 #include <boost/config/abi_prefix.hpp>
 
@@ -43,7 +47,17 @@
         }
 
 
+#ifndef BOOST_NO_DELETED_FUNCTIONS
+ public:
+ shared_mutex(shared_mutex const&) = delete;
+ shared_mutex& operator=(shared_mutex const&) = delete;
+#else // BOOST_NO_DELETED_FUNCTIONS
+ private:
+ shared_mutex(shared_mutex const&);
+ shared_mutex& operator=(shared_mutex const&);
+#endif // BOOST_NO_DELETED_FUNCTIONS
     public:
+
         shared_mutex()
         {
             state_data state_={0,0,0,0};
@@ -102,7 +116,40 @@
         {
             return timed_lock_shared(get_system_time()+relative_time);
         }
-
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+
+ while(state.exclusive || state.exclusive_waiting_blocked)
+ {
+ if(cv_status::timeout==shared_cond.wait_for(lk,rel_time))
+ {
+ return false;
+ }
+ }
+ ++state.shared_count;
+ return true;
+ }
+ template <class Clock, class Duration>
+ bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+
+ while(state.exclusive || state.exclusive_waiting_blocked)
+ {
+ if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
+ {
+ return false;
+ }
+ }
+ ++state.shared_count;
+ return true;
+ }
+#endif
         void unlock_shared()
         {
             boost::mutex::scoped_lock lk(state_change);
@@ -166,6 +213,55 @@
             return timed_lock(get_system_time()+relative_time);
         }
 
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+
+ while(state.shared_count || state.exclusive)
+ {
+ state.exclusive_waiting_blocked=true;
+ if(cv_status::timeout == exclusive_cond.wait_for(lk,rel_time))
+ {
+ if(state.shared_count || state.exclusive)
+ {
+ state.exclusive_waiting_blocked=false;
+ release_waiters();
+ return false;
+ }
+ break;
+ }
+ }
+ state.exclusive=true;
+ return true;
+ }
+ template <class Clock, class Duration>
+ bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+
+ while(state.shared_count || state.exclusive)
+ {
+ state.exclusive_waiting_blocked=true;
+ if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
+ {
+ if(state.shared_count || state.exclusive)
+ {
+ state.exclusive_waiting_blocked=false;
+ release_waiters();
+ return false;
+ }
+ break;
+ }
+ }
+ state.exclusive=true;
+ return true;
+ }
+#endif
+
         bool try_lock()
         {
             boost::mutex::scoped_lock lk(state_change);

Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2 (original)
+++ trunk/libs/thread/test/Jamfile.v2 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -78,6 +78,7 @@
           [ thread-run test_shared_mutex.cpp ]
           [ thread-run test_shared_mutex_part_2.cpp ]
           [ thread-run test_shared_mutex_timed_locks.cpp ]
+ #[ thread-run test_shared_mutex_timed_locks_chrono.cpp ]
           [ thread-run test_lock_concept.cpp ]
           [ thread-run test_generic_locks.cpp ]
           [ thread-run test_futures.cpp ]
@@ -206,13 +207,21 @@
 
           [ thread-compile-fail-V2 ./sync/mutual_exclusion/timed_mutex/assign_fail.cpp : : mutual_exclusion__timed_mutex__assign_fail ]
           [ thread-compile-fail-V2 ./sync/mutual_exclusion/timed_mutex/copy_fail.cpp : : mutual_exclusion__timed_mutex__copy_fail ]
-
           [ thread-run2 ./sync/mutual_exclusion/timed_mutex/default_pass.cpp : mutual_exclusion__timed_mutex__default_pass ]
           [ thread-run2 ./sync/mutual_exclusion/timed_mutex/lock_pass.cpp : mutual_exclusion__timed_mutex__lock_pass ]
           [ thread-run2 ./sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp : mutual_exclusion__timed_mutex__native_handle_pass ]
           [ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp : mutual_exclusion__timed_mutex__try_lock_for_pass ]
           [ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp : mutual_exclusion__timed_mutex__try_lock_pass ]
           [ thread-run2 ./sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp : mutual_exclusion__timed_mutex__try_lock_until_pass ]
+
+ [ thread-compile-fail-V2 ./sync/mutual_exclusion/shared_mutex/assign_fail.cpp : : mutual_exclusion__shared_mutex__assign_fail ]
+ [ thread-compile-fail-V2 ./sync/mutual_exclusion/shared_mutex/copy_fail.cpp : : mutual_exclusion__shared_mutex__copy_fail ]
+ [ thread-run2 ./sync/mutual_exclusion/shared_mutex/default_pass.cpp : mutual_exclusion__shared_mutex__default_pass ]
+ [ thread-run2 ./sync/mutual_exclusion/shared_mutex/lock_pass.cpp : mutual_exclusion__shared_mutex__lock_pass ]
+ #[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp : mutual_exclusion__shared_mutex__try_lock_for_pass ]
+ [ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp : mutual_exclusion__shared_mutex__try_lock_pass ]
+ #[ thread-run2 ./sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp : mutual_exclusion__shared_mutex__try_lock_until_pass ]
+
     ;
 
     #explicit this_thread ;

Added: trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+// <boost/thread/shared_mutex.hpp>
+
+// class shared_mutex;
+
+// shared_mutex& operator=(const shared_mutex&) = delete;
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ boost::shared_mutex m0;
+ boost::shared_mutex m1(m0);
+}
+

Added: trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+// <boost/thread/shared_mutex.hpp>
+
+// class shared_mutex;
+
+// shared_mutex(const shared_mutex&) = delete;
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ boost::shared_mutex m0;
+ boost::shared_mutex m1(m0);
+}
+

Added: trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+// <boost/thread/timed_mutex.hpp>
+
+// class shared_mutex;
+
+// shared_mutex();
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ boost::shared_mutex m0;
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+// <boost/thread/shared_mutex.hpp>
+
+// class shared_mutex;
+
+// void lock();
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+boost::shared_mutex m;
+
+typedef boost::chrono::system_clock Clock;
+typedef Clock::time_point time_point;
+typedef Clock::duration duration;
+typedef boost::chrono::milliseconds ms;
+typedef boost::chrono::nanoseconds ns;
+
+void f()
+{
+ time_point t0 = Clock::now();
+ m.lock();
+ time_point t1 = Clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_TEST(d < ns(2500000)+ms(1000)); // within 2.5ms
+}
+
+int main()
+{
+ m.lock();
+ boost::thread t(f);
+ boost::this_thread::sleep_for(ms(250));
+ m.unlock();
+ t.join();
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+// <boost/thread/shared_mutex.hpp>
+
+// class shared_mutex;
+
+// template <class Rep, class Period>
+// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+boost::shared_mutex m;
+
+typedef boost::chrono::steady_clock Clock;
+typedef Clock::time_point time_point;
+typedef Clock::duration duration;
+typedef boost::chrono::milliseconds ms;
+typedef boost::chrono::nanoseconds ns;
+
+void f1()
+{
+ time_point t0 = Clock::now();
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_TEST(m.try_lock_for(ms(300)+ms(1000)) == true);
+ time_point t1 = Clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
+}
+
+void f2()
+{
+ time_point t0 = Clock::now();
+ BOOST_TEST(m.try_lock_for(ms(250)) == false);
+ time_point t1 = Clock::now();
+ ns d = t1 - t0 - ms(250);
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
+}
+
+int main()
+{
+ {
+ m.lock();
+ boost::thread t(f1);
+ boost::this_thread::sleep_for(ms(250));
+ m.unlock();
+ t.join();
+ }
+ {
+ m.lock();
+ boost::thread t(f2);
+ boost::this_thread::sleep_for(ms(300));
+ m.unlock();
+ t.join();
+ }
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+// <boost/thread/shared_mutex.hpp>
+
+// class shared_mutex;
+
+// bool try_lock();
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+boost::shared_mutex m;
+
+typedef boost::chrono::system_clock Clock;
+typedef Clock::time_point time_point;
+typedef Clock::duration duration;
+typedef boost::chrono::milliseconds ms;
+typedef boost::chrono::nanoseconds ns;
+
+void f()
+{
+ time_point t0 = Clock::now();
+ BOOST_TEST(!m.try_lock());
+ BOOST_TEST(!m.try_lock());
+ BOOST_TEST(!m.try_lock());
+ while (!m.try_lock())
+ ;
+ time_point t1 = Clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_TEST(d < ns(50000000)+ms(1000)); // within 50ms
+}
+
+int main()
+{
+ m.lock();
+ boost::thread t(f);
+ boost::this_thread::sleep_for(ms(250));
+ m.unlock();
+ t.join();
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+// <boost/thread/shared_mutex.hpp>
+
+// class shared_mutex;
+
+// template <class Clock, class Duration>
+// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+boost::shared_mutex m;
+
+typedef boost::chrono::steady_clock Clock;
+typedef Clock::time_point time_point;
+typedef Clock::duration duration;
+typedef boost::chrono::milliseconds ms;
+typedef boost::chrono::nanoseconds ns;
+
+void f1()
+{
+ time_point t0 = Clock::now();
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_TEST(m.try_lock_until(Clock::now() + ms(300) + ms(1000)) == true);
+ time_point t1 = Clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
+}
+
+void f2()
+{
+ time_point t0 = Clock::now();
+ BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == false);
+ time_point t1 = Clock::now();
+ ns d = t1 - t0 - ms(250);
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_TEST(d < ns(5000000)+ms(1000)); // within 5ms
+}
+
+int main()
+{
+ {
+ m.lock();
+ boost::thread t(f1);
+ boost::this_thread::sleep_for(ms(250));
+ m.unlock();
+ t.join();
+ }
+ {
+ m.lock();
+ boost::thread t(f2);
+ boost::this_thread::sleep_for(ms(300));
+ m.unlock();
+ t.join();
+ }
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp 2012-02-12 17:38:59 EST (Sun, 12 Feb 2012)
@@ -0,0 +1,269 @@
+// (C) Copyright 2006-7 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/test/unit_test.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/shared_mutex.hpp>
+//#include <boost/thread/xtime.hpp>
+#include "util.inl"
+#include "shared_mutex_locking_thread.hpp"
+
+#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
+ { \
+ boost::mutex::scoped_lock lock(mutex_name); \
+ BOOST_CHECK_EQUAL(value,expected_value); \
+ }
+
+
+void test_timed_lock_shared_times_out_if_write_lock_held()
+{
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+ unsigned unblocked_count=0;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
+
+ boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now();
+ boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500);
+ boost::chrono::milliseconds const timeout_resolution(50);
+ bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout);
+ BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now());
+ BOOST_CHECK(!timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ boost::chrono::milliseconds const wait_duration(500);
+ boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration;
+ timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration);
+ BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now());
+ BOOST_CHECK(!timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ finish_lock.unlock();
+ writer.join();
+}
+
+void test_timed_lock_shared_succeeds_if_no_lock_held()
+{
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+
+ boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now();
+ boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500);
+ boost::chrono::milliseconds const timeout_resolution(50);
+ bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout);
+ BOOST_CHECK(boost::chrono::steady_clock::now()<timeout);
+ BOOST_CHECK(timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ boost::chrono::milliseconds const wait_duration(500);
+ boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration;
+ timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration);
+ BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2);
+ BOOST_CHECK(timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+}
+
+void test_timed_lock_shared_succeeds_if_read_lock_held()
+{
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+ unsigned unblocked_count=0;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
+
+ boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now();
+ boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500);
+ boost::chrono::milliseconds const timeout_resolution(50);
+ bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout);
+ BOOST_CHECK(boost::chrono::steady_clock::now()<timeout);
+ BOOST_CHECK(timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ boost::chrono::milliseconds const wait_duration(500);
+ boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration;
+ timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration);
+ BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2);
+ BOOST_CHECK(timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ finish_lock.unlock();
+ reader.join();
+}
+
+void test_timed_lock_times_out_if_write_lock_held()
+{
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+ unsigned unblocked_count=0;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
+
+ boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now();
+ boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500);
+ boost::chrono::milliseconds const timeout_resolution(50);
+ bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout);
+ BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now());
+ BOOST_CHECK(!timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock();
+ }
+
+ boost::chrono::milliseconds const wait_duration(500);
+ boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration;
+ timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration);
+ BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now());
+ BOOST_CHECK(!timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock();
+ }
+
+ finish_lock.unlock();
+ writer.join();
+}
+
+void test_timed_lock_succeeds_if_no_lock_held()
+{
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+
+ boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now();
+ boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500);
+ boost::chrono::milliseconds const timeout_resolution(50);
+ bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout);
+ BOOST_CHECK(boost::chrono::steady_clock::now()<timeout);
+ BOOST_CHECK(timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock();
+ }
+
+ boost::chrono::milliseconds const wait_duration(500);
+ boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration;
+ timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration);
+ BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2);
+ BOOST_CHECK(timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock();
+ }
+
+}
+
+void test_timed_lock_times_out_if_read_lock_held()
+{
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+ unsigned unblocked_count=0;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
+
+ boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now();
+ boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500);
+ boost::chrono::milliseconds const timeout_resolution(50);
+ bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout);
+ BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now());
+ BOOST_CHECK(!timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock();
+ }
+
+ boost::chrono::milliseconds const wait_duration(500);
+ boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration;
+ timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration);
+ BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now());
+ BOOST_CHECK(!timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock();
+ }
+
+ finish_lock.unlock();
+ reader.join();
+}
+
+void test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held()
+{
+ boost::shared_mutex rw_mutex;
+ boost::mutex finish_mutex;
+ boost::mutex unblocked_mutex;
+ unsigned unblocked_count=0;
+ boost::mutex::scoped_lock finish_lock(finish_mutex);
+ boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
+
+ boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now();
+ boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500);
+ bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout);
+ BOOST_CHECK(!timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock();
+ }
+
+ boost::chrono::milliseconds const wait_duration(500);
+ timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration);
+ BOOST_CHECK(timed_lock_succeeded);
+ if(timed_lock_succeeded)
+ {
+ rw_mutex.unlock_shared();
+ }
+
+ finish_lock.unlock();
+ reader.join();
+}
+
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
+
+ test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held));
+ test->add(BOOST_TEST_CASE(&test_timed_lock_shared_succeeds_if_no_lock_held));
+ test->add(BOOST_TEST_CASE(&test_timed_lock_shared_succeeds_if_read_lock_held));
+ test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_if_write_lock_held));
+ test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_if_read_lock_held));
+ test->add(BOOST_TEST_CASE(&test_timed_lock_succeeds_if_no_lock_held));
+ test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held));
+
+ return test;
+}


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