Index: pthread/shared_mutex.hpp =================================================================== --- pthread/shared_mutex.hpp (revision 77668) +++ pthread/shared_mutex.hpp (working copy) @@ -437,6 +437,57 @@ release_waiters(); } +#ifdef BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION + bool try_unlock_shared_and_lock() + { + boost::mutex::scoped_lock lk(state_change); + if( !state.exclusive + && !state.exclusive_waiting_blocked + && !state.upgrade + && state.shared_count==1) + { + state.shared_count=0; + state.exclusive=true; + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + try_unlock_shared_and_lock_for( + const chrono::duration& rel_time) + { + return try_unlock_shared_and_lock_until( + chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_shared_and_lock_until( + const chrono::time_point& abs_time) + { + boost::this_thread::disable_interruption do_not_disturb; + boost::mutex::scoped_lock lk(state_change); + if (state.shared_count != 1) + { + while (true) + { + cv_status status = shared_cond.wait_until(lk,abs_time); + if (state.shared_count == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=false; + state.exclusive=true; + state.exclusive_waiting_blocked=false; + state.shared_count=0; + return true; + } +#endif +#endif + // Shared <-> Upgrade void unlock_upgrade_and_lock_shared() { @@ -446,6 +497,58 @@ release_waiters(); } +#ifdef BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION + bool try_unlock_shared_and_lock_upgrade() + { + boost::mutex::scoped_lock lk(state_change); + if( !state.exclusive + && !state.exclusive_waiting_blocked + && !state.upgrade + ) + { + state.upgrade=true; + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + try_unlock_shared_and_lock_upgrade_for( + const chrono::duration& rel_time) + { + return try_unlock_shared_and_lock_upgrade_until( + chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_shared_and_lock_upgrade_until( + const chrono::time_point& abs_time) + { + boost::this_thread::disable_interruption do_not_disturb; + boost::mutex::scoped_lock lk(state_change); + if( state.exclusive + || state.exclusive_waiting_blocked + || state.upgrade + ) + { + while (true) + { + cv_status status = exclusive_cond.wait_until(lk,abs_time); + if( ! state.exclusive + && ! state.exclusive_waiting_blocked + && ! state.upgrade + ) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=true; + return true; + } +#endif +#endif }; typedef shared_mutex upgrade_mutex; Index: locks.hpp =================================================================== --- locks.hpp (revision 77668) +++ locks.hpp (working copy) @@ -640,6 +640,181 @@ #endif #endif +#ifdef BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION +#ifndef BOOST_NO_RVALUE_REFERENCES + // Conversion from shared locking + unique_lock(shared_lock&& sl, try_to_lock_t) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock()) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + +#ifdef BOOST_THREAD_USES_CHRONO + template + unique_lock(shared_lock&& sl, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_until(abs_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + + template + unique_lock(shared_lock&& sl, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_for(rel_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#endif +#else + +#if defined BOOST_THREAD_USES_MOVE + + // Conversion from shared locking + unique_lock(boost::rv >& sl, try_to_lock_t) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock()) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + +#ifdef BOOST_THREAD_USES_CHRONO + template + unique_lock(boost::rv >& sl, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_until(abs_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + + template + unique_lock(boost::rv >& sl, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_for(rel_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#endif +#else + + // Conversion from shared locking + unique_lock(detail::thread_move_t > sl, try_to_lock_t) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock()) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + +#ifdef BOOST_THREAD_USES_CHRONO + template + unique_lock(detail::thread_move_t > sl, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_until(abs_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + + template + unique_lock(detail::thread_move_t > sl, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_for(rel_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#endif +#endif +#endif +#endif + + void swap(unique_lock& other) BOOST_NOEXCEPT { std::swap(m,other.m); @@ -836,7 +1011,7 @@ public: typedef Mutex mutex_type; - shared_lock(): + shared_lock() BOOST_NOEXCEPT: m(0),is_locked(false) {} @@ -848,7 +1023,7 @@ shared_lock(Mutex& m_,adopt_lock_t): m(&m_),is_locked(true) {} - shared_lock(Mutex& m_,defer_lock_t): + shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: m(&m_),is_locked(false) {} shared_lock(Mutex& m_,try_to_lock_t): @@ -876,7 +1051,7 @@ #endif #ifndef BOOST_NO_RVALUE_REFERENCES - shared_lock(shared_lock && other): + shared_lock(shared_lock && other) BOOST_NOEXCEPT: m(other.m),is_locked(other.is_locked) { other.is_locked=false; @@ -906,7 +1081,7 @@ } - shared_lock& operator=(shared_lock && other) + shared_lock& operator=(shared_lock && other) BOOST_NOEXCEPT { shared_lock temp(::boost::move(other)); swap(temp); @@ -930,7 +1105,7 @@ #endif #else #if defined BOOST_THREAD_USES_MOVE - shared_lock(boost::rv >& other): + shared_lock(boost::rv >& other) BOOST_NOEXCEPT: m(other.m),is_locked(other.is_locked) { other.is_locked=false; @@ -959,24 +1134,24 @@ other.m=0; } - operator ::boost::rv >&() + operator ::boost::rv >&() BOOST_NOEXCEPT { return *static_cast< ::boost::rv >* >(this); } - operator const ::boost::rv >&() const + operator const ::boost::rv >&() const BOOST_NOEXCEPT { return *static_cast >* >(this); } - ::boost::rv >& move() + ::boost::rv >& move() BOOST_NOEXCEPT { return *static_cast< ::boost::rv >* >(this); } - const ::boost::rv >& move() const + const ::boost::rv >& move() const BOOST_NOEXCEPT { return *static_cast >* >(this); } - shared_lock& operator=(::boost::rv >& other) + shared_lock& operator=(::boost::rv >& other) BOOST_NOEXCEPT { shared_lock temp(other); swap(temp); @@ -1000,7 +1175,7 @@ #endif #else - shared_lock(detail::thread_move_t > other): + shared_lock(detail::thread_move_t > other) BOOST_NOEXCEPT: m(other->m),is_locked(other->is_locked) { other->is_locked=false; @@ -1029,18 +1204,18 @@ other->m=0; } - operator detail::thread_move_t >() + operator detail::thread_move_t >() BOOST_NOEXCEPT { return move(); } - detail::thread_move_t > move() + detail::thread_move_t > move() BOOST_NOEXCEPT { return detail::thread_move_t >(*this); } - shared_lock& operator=(detail::thread_move_t > other) + shared_lock& operator=(detail::thread_move_t > other) BOOST_NOEXCEPT { shared_lock temp(other); swap(temp); @@ -1065,13 +1240,13 @@ #endif #endif - void swap(shared_lock& other) + void swap(shared_lock& other) BOOST_NOEXCEPT { std::swap(m,other.m); std::swap(is_locked,other.is_locked); } - Mutex* mutex() const + Mutex* mutex() const BOOST_NOEXCEPT { return m; } @@ -1190,21 +1365,21 @@ #if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS) typedef void (shared_lock::*bool_type)(); - operator bool_type() const + operator bool_type() const BOOST_NOEXCEPT { return is_locked?&shared_lock::lock:0; } - bool operator!() const + bool operator!() const BOOST_NOEXCEPT { return !owns_lock(); } #else - explicit operator bool() const + explicit operator bool() const BOOST_NOEXCEPT { return owns_lock(); } #endif - bool owns_lock() const + bool owns_lock() const BOOST_NOEXCEPT { return is_locked; } @@ -1218,8 +1393,9 @@ {}; #endif + template - void swap(shared_lock& lhs,shared_lock& rhs) + void swap(shared_lock& lhs,shared_lock& rhs) BOOST_NOEXCEPT { lhs.swap(rhs); } @@ -1241,7 +1417,7 @@ #endif public: typedef Mutex mutex_type; - upgrade_lock(): + upgrade_lock() BOOST_NOEXCEPT: m(0),is_locked(false) {} @@ -1253,7 +1429,7 @@ upgrade_lock(Mutex& m_,adopt_lock_t): m(&m_),is_locked(true) {} - upgrade_lock(Mutex& m_,defer_lock_t): + upgrade_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: m(&m_),is_locked(false) {} upgrade_lock(Mutex& m_,try_to_lock_t): @@ -1276,7 +1452,7 @@ #endif #ifndef BOOST_NO_RVALUE_REFERENCES - upgrade_lock(upgrade_lock&& other): + upgrade_lock(upgrade_lock&& other) BOOST_NOEXCEPT: m(other.m),is_locked(other.is_locked) { other.is_locked=false; @@ -1294,7 +1470,7 @@ other.m=0; } - upgrade_lock& operator=(upgrade_lock&& other) + upgrade_lock& operator=(upgrade_lock&& other) BOOST_NOEXCEPT { upgrade_lock temp(::boost::move(other)); swap(temp); @@ -1311,7 +1487,7 @@ #endif #else #if defined BOOST_THREAD_USES_MOVE - upgrade_lock(boost::rv >& other): + upgrade_lock(boost::rv >& other) BOOST_NOEXCEPT: m(other.m),is_locked(other.is_locked) { other.is_locked=false; @@ -1329,23 +1505,23 @@ other.m=0; } - operator ::boost::rv&() + operator ::boost::rv&() BOOST_NOEXCEPT { return *static_cast< ::boost::rv* >(this); } - operator const ::boost::rv&() const + operator const ::boost::rv&() const BOOST_NOEXCEPT { return *static_cast* >(this); } - ::boost::rv& move() + ::boost::rv& move() BOOST_NOEXCEPT { return *static_cast< ::boost::rv* >(this); } - const ::boost::rv& move() const + const ::boost::rv& move() const BOOST_NOEXCEPT { return *static_cast* >(this); } - upgrade_lock& operator=(boost::rv >& other) + upgrade_lock& operator=(boost::rv >& other) BOOST_NOEXCEPT { upgrade_lock temp(other); swap(temp); @@ -1361,7 +1537,7 @@ } #endif #else - upgrade_lock(detail::thread_move_t > other): + upgrade_lock(detail::thread_move_t > other) BOOST_NOEXCEPT: m(other->m),is_locked(other->is_locked) { other->is_locked=false; @@ -1379,18 +1555,18 @@ other->m=0; } - operator detail::thread_move_t >() + operator detail::thread_move_t >() BOOST_NOEXCEPT { return move(); } - detail::thread_move_t > move() + detail::thread_move_t > move() BOOST_NOEXCEPT { return detail::thread_move_t >(*this); } - upgrade_lock& operator=(detail::thread_move_t > other) + upgrade_lock& operator=(detail::thread_move_t > other) BOOST_NOEXCEPT { upgrade_lock temp(other); swap(temp); @@ -1408,12 +1584,185 @@ #endif #endif - void swap(upgrade_lock& other) +#ifdef BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION +#ifndef BOOST_NO_RVALUE_REFERENCES + // Conversion from shared locking + + upgrade_lock(shared_lock&& sl, try_to_lock_t) + : m(0),is_locked(false) { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade()) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#ifdef BOOST_THREAD_USES_CHRONO + template + upgrade_lock(shared_lock&& sl, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + + template + upgrade_lock(shared_lock&& sl, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#endif +#else + + +#if defined BOOST_THREAD_USES_MOVE + // Conversion from shared locking + + upgrade_lock(boost::rv > &sl, try_to_lock_t) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade()) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#ifdef BOOST_THREAD_USES_CHRONO + template + upgrade_lock(boost::rv > &sl, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + + template + upgrade_lock(boost::rv > &sl, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#endif +#else + // Conversion from shared locking + + upgrade_lock(detail::thread_move_t > sl, try_to_lock_t) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade()) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#ifdef BOOST_THREAD_USES_CHRONO + template + upgrade_lock(detail::thread_move_t > sl, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } + + template + upgrade_lock(detail::thread_move_t >& sl, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (sl.owns_lock()) { + if (sl.mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time)) + { + m = sl.release(); + is_locked = true; + } + } + else + { + m = sl.release(); + } + } +#endif +#endif +#endif +#endif + + void swap(upgrade_lock& other) BOOST_NOEXCEPT + { std::swap(m,other.m); std::swap(is_locked,other.is_locked); } - Mutex* mutex() const + Mutex* mutex() const BOOST_NOEXCEPT { return m; } @@ -1503,21 +1852,21 @@ #endif #if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS) typedef void (upgrade_lock::*bool_type)(); - operator bool_type() const + operator bool_type() const BOOST_NOEXCEPT { return is_locked?&upgrade_lock::lock:0; } - bool operator!() const + bool operator!() const BOOST_NOEXCEPT { return !owns_lock(); } #else - explicit operator bool() const + explicit operator bool() const BOOST_NOEXCEPT { return owns_lock(); } #endif - bool owns_lock() const + bool owns_lock() const BOOST_NOEXCEPT { return is_locked; } @@ -1605,13 +1954,13 @@ } #ifndef BOOST_NO_RVALUE_REFERENCES - upgrade_to_unique_lock(upgrade_to_unique_lock&& other): + upgrade_to_unique_lock(upgrade_to_unique_lock&& other) BOOST_NOEXCEPT: source(other.source),exclusive(::boost::move(other.exclusive)) { other.source=0; } - upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&& other) + upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&& other) BOOST_NOEXCEPT { upgrade_to_unique_lock temp(other); swap(temp); @@ -1619,59 +1968,59 @@ } #else #if defined BOOST_THREAD_USES_MOVE - upgrade_to_unique_lock(boost::rv >& other): + upgrade_to_unique_lock(boost::rv >& other) BOOST_NOEXCEPT: source(other.source),exclusive(::boost::move(other.exclusive)) { other.source=0; } - upgrade_to_unique_lock& operator=(boost::rv >& other) + upgrade_to_unique_lock& operator=(boost::rv >& other) BOOST_NOEXCEPT { upgrade_to_unique_lock temp(other); swap(temp); return *this; } - operator ::boost::rv&() + operator ::boost::rv&() BOOST_NOEXCEPT { return *static_cast< ::boost::rv* >(this); } - operator const ::boost::rv&() const + operator const ::boost::rv&() const BOOST_NOEXCEPT { return *static_cast* >(this); } - ::boost::rv& move() + ::boost::rv& move() BOOST_NOEXCEPT { return *static_cast< ::boost::rv* >(this); } - const ::boost::rv& move() const + const ::boost::rv& move() const BOOST_NOEXCEPT { return *static_cast* >(this); } #else - upgrade_to_unique_lock(detail::thread_move_t > other): + upgrade_to_unique_lock(detail::thread_move_t > other) BOOST_NOEXCEPT: source(other->source),exclusive(::boost::move(other->exclusive)) { other->source=0; } - upgrade_to_unique_lock& operator=(detail::thread_move_t > other) + upgrade_to_unique_lock& operator=(detail::thread_move_t > other) BOOST_NOEXCEPT { upgrade_to_unique_lock temp(other); swap(temp); return *this; } - operator detail::thread_move_t >() + operator detail::thread_move_t >() BOOST_NOEXCEPT { return move(); } - detail::thread_move_t > move() + detail::thread_move_t > move() BOOST_NOEXCEPT { return detail::thread_move_t >(*this); } #endif #endif - void swap(upgrade_to_unique_lock& other) + void swap(upgrade_to_unique_lock& other) BOOST_NOEXCEPT { std::swap(source,other.source); exclusive.swap(other.exclusive); @@ -1679,22 +2028,22 @@ #if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS) typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&); - operator bool_type() const + operator bool_type() const BOOST_NOEXCEPT { return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0; } - bool operator!() const + bool operator!() const BOOST_NOEXCEPT { return !owns_lock(); } #else - explicit operator bool() const + explicit operator bool() const BOOST_NOEXCEPT { return owns_lock(); } #endif - bool owns_lock() const + bool owns_lock() const BOOST_NOEXCEPT { return exclusive.owns_lock(); } Index: ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp =================================================================== --- ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp (revision 0) +++ ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp (revision 0) @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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) 2011 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) + +// + +// template class upgrade_lock; + +// upgrade_lock(shared_lock&& u, try_to_lock); + +#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_SHARED_MUTEX_GENERIC + +#include +#include +#include + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock lk0(m); + boost::upgrade_lock lk(boost::move(lk0), boost::try_to_lock ); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock lk(boost::shared_lock(m), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + boost::upgrade_lock lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + Property changes on: ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Id Added: svn:eol-style + native Index: ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp =================================================================== --- ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp (revision 0) +++ ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp (revision 0) @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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) 2011 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) + +// + +// template class upgrade_lock; + +// template +// upgrade_lock(shared_lock&&, +// const chrono::duration&); + +#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_SHARED_MUTEX_GENERIC + +#include +#include +#include + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock lk0(m); + boost::upgrade_lock lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock + lk(boost::shared_lock(m), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + boost::upgrade_lock lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + Property changes on: ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Id Added: svn:eol-style + native Index: ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp =================================================================== --- ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp (revision 0) +++ ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp (revision 0) @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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) 2011 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) + +// + +// template class upgrade_lock; + +// template +// upgrade_lock(shared_lock&&, +// const chrono::time_point&); + +#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_SHARED_MUTEX_GENERIC + +#include +#include +#include + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock lk0(m); + boost::upgrade_lock lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock + lk( boost::shared_lock(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + boost::upgrade_lock lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + Property changes on: ../../libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Id Added: svn:eol-style + native Index: ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp =================================================================== --- ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp (revision 0) +++ ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp (revision 0) @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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) 2011 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) + +// + +// template class unique_lock; + +// unique_lock(shared_lock&& u, try_to_lock); + +#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_SHARED_MUTEX_GENERIC + +#include +#include +#include + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock lk0(m); + boost::unique_lock lk(boost::move(lk0), boost::try_to_lock ); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock lk(boost::shared_lock(m), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + boost::unique_lock lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + Property changes on: ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Id Added: svn:eol-style + native Index: ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp =================================================================== --- ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp (revision 0) +++ ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp (revision 0) @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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) 2011 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) + +// + +// template class unique_lock; + +// template +// unique_lock(shared_lock&&, +// const chrono::duration&); + +#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_SHARED_MUTEX_GENERIC + +#include +#include +#include + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock lk0(m); + boost::unique_lock lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock + lk(boost::shared_lock(m), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + boost::unique_lock lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + Property changes on: ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Id Added: svn:eol-style + native Index: ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp =================================================================== --- ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp (revision 0) +++ ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp (revision 0) @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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) 2011 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) + +// + +// template class unique_lock; + +// template +// unique_lock(shared_lock&&, +// const chrono::time_point&); + +#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_SHARED_MUTEX_GENERIC + +#include +#include +#include + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock lk0(m); + boost::unique_lock lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock + lk( boost::shared_lock(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + boost::unique_lock lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + Property changes on: ../../libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Id Added: svn:eol-style + native Index: ../../libs/thread/build/Jamfile.v2 =================================================================== --- ../../libs/thread/build/Jamfile.v2 (revision 77640) +++ ../../libs/thread/build/Jamfile.v2 (working copy) @@ -225,7 +225,7 @@ explicit thread_sources ; lib boost_thread - : thread_sources future.cpp + : thread_sources future.cpp shared_mutex.cpp : @requirements : : shared:BOOST_THREAD_USE_DLL=1 Index: ../../libs/thread/src/shared_mutex.cpp =================================================================== --- ../../libs/thread/src/shared_mutex.cpp (revision 0) +++ ../../libs/thread/src/shared_mutex.cpp (revision 0) @@ -0,0 +1,328 @@ +// Copyright Howard Hinnant 2007-2010. +// Copyright Vicente J. Botet Escriba 2012. +// Use, modification and distribution are subject to 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 +#include + +namespace boost +{ + + namespace thread_v2 + { + + // shared_mutex + + shared_mutex::shared_mutex() + : state_(0) + { + } + + shared_mutex::~shared_mutex() + { + boost::lock_guard _(mut_); + } + + // Exclusive ownership + + void + shared_mutex::lock() + { + boost::unique_lock lk(mut_); + while (state_ & write_entered_) + gate1_.wait(lk); + state_ |= write_entered_; + while (state_ & n_readers_) + gate2_.wait(lk); + } + + bool + shared_mutex::try_lock() + { + boost::unique_lock lk(mut_); + if (state_ == 0) + { + state_ = write_entered_; + return true; + } + return false; + } + + void + shared_mutex::unlock() + { + boost::lock_guard _(mut_); + state_ = 0; + gate1_.notify_all(); + } + + // Shared ownership + + void + shared_mutex::lock_shared() + { + boost::unique_lock lk(mut_); + while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) + gate1_.wait(lk); + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; + } + + bool + shared_mutex::try_lock_shared() + { + boost::unique_lock lk(mut_); + count_t num_readers = state_ & n_readers_; + if (!(state_ & write_entered_) && num_readers != n_readers_) + { + ++num_readers; + state_ &= ~n_readers_; + state_ |= num_readers; + return true; + } + return false; + } + + void + shared_mutex::unlock_shared() + { + boost::lock_guard _(mut_); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~n_readers_; + state_ |= num_readers; + if (state_ & write_entered_) + { + if (num_readers == 0) + gate2_.notify_one(); + } + else + { + if (num_readers == n_readers_ - 1) + gate1_.notify_one(); + } + } + + // upgrade_mutex + + upgrade_mutex::upgrade_mutex() + : gate1_(), + gate2_(), + state_(0) + { + } + + upgrade_mutex::~upgrade_mutex() + { + boost::lock_guard _(mut_); + } + + // Exclusive ownership + + void + upgrade_mutex::lock() + { + boost::unique_lock lk(mut_); + while (state_ & (write_entered_ | upgradable_entered_)) + gate1_.wait(lk); + state_ |= write_entered_; + while (state_ & n_readers_) + gate2_.wait(lk); + } + + bool + upgrade_mutex::try_lock() + { + boost::unique_lock lk(mut_); + if (state_ == 0) + { + state_ = write_entered_; + return true; + } + return false; + } + + void + upgrade_mutex::unlock() + { + boost::lock_guard _(mut_); + state_ = 0; + gate1_.notify_all(); + } + + // Shared ownership + + void + upgrade_mutex::lock_shared() + { + boost::unique_lock lk(mut_); + while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) + gate1_.wait(lk); + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; + } + + bool + upgrade_mutex::try_lock_shared() + { + boost::unique_lock lk(mut_); + count_t num_readers = state_ & n_readers_; + if (!(state_ & write_entered_) && num_readers != n_readers_) + { + ++num_readers; + state_ &= ~n_readers_; + state_ |= num_readers; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_shared() + { + boost::lock_guard _(mut_); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~n_readers_; + state_ |= num_readers; + if (state_ & write_entered_) + { + if (num_readers == 0) + gate2_.notify_one(); + } + else + { + if (num_readers == n_readers_ - 1) + gate1_.notify_one(); + } + } + + // Upgrade ownership + + void + upgrade_mutex::lock_upgrade() + { + boost::unique_lock lk(mut_); + while ((state_ & (write_entered_ | upgradable_entered_)) || + (state_ & n_readers_) == n_readers_) + gate1_.wait(lk); + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= upgradable_entered_ | num_readers; + } + + bool + upgrade_mutex::try_lock_upgrade() + { + boost::unique_lock lk(mut_); + count_t num_readers = state_ & n_readers_; + if (!(state_ & (write_entered_ | upgradable_entered_)) + && num_readers != n_readers_) + { + ++num_readers; + state_ &= ~n_readers_; + state_ |= upgradable_entered_ | num_readers; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_upgrade() + { + { + boost::lock_guard _(mut_); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~(upgradable_entered_ | n_readers_); + state_ |= num_readers; + } + gate1_.notify_all(); + } + + // Shared <-> Exclusive + + bool + upgrade_mutex::try_unlock_shared_and_lock() + { + boost::unique_lock lk(mut_); + if (state_ == 1) + { + state_ = write_entered_; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_and_lock_shared() + { + { + boost::lock_guard _(mut_); + state_ = 1; + } + gate1_.notify_all(); + } + + // Shared <-> Upgrade + + bool + upgrade_mutex::try_unlock_shared_and_lock_upgrade() + { + boost::unique_lock lk(mut_); + if (!(state_ & (write_entered_ | upgradable_entered_))) + { + state_ |= upgradable_entered_; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_upgrade_and_lock_shared() + { + { + boost::lock_guard _(mut_); + state_ &= ~upgradable_entered_; + } + gate1_.notify_all(); + } + + // Upgrade <-> Exclusive + + void + upgrade_mutex::unlock_upgrade_and_lock() + { + boost::unique_lock lk(mut_); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~(upgradable_entered_ | n_readers_); + state_ |= write_entered_ | num_readers; + while (state_ & n_readers_) + gate2_.wait(lk); + } + + bool + upgrade_mutex::try_unlock_upgrade_and_lock() + { + boost::unique_lock lk(mut_); + if (state_ == (upgradable_entered_ | 1)) + { + state_ = write_entered_; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_and_lock_upgrade() + { + { + boost::lock_guard _(mut_); + state_ = upgradable_entered_ | 1; + } + gate1_.notify_all(); + } + + } // thread_v2 +} // boost Property changes on: ../../libs/thread/src/shared_mutex.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Id Added: svn:eol-style + native