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