Thread: Added shared mutex upwards conversion + configuration macros

[SVN r77704]
This commit is contained in:
Vicente J. Botet Escriba 2012-04-01 21:52:47 +00:00
parent 09d5125278
commit 08ed4c4201
21 changed files with 1597 additions and 112 deletions

View File

@ -161,14 +161,7 @@ rule usage-requirements ( properties * )
}
}
if <toolset>vacpp in $(properties)
{
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
}
else
{
result += <library>/boost/chrono//boost_chrono ;
}
result += <library>/boost/chrono//boost_chrono ;
return $(result) ;
}
@ -193,14 +186,7 @@ rule requirements ( properties * )
}
}
}
if <toolset>vacpp in $(properties)
{
result += <define>BOOST_THREAD_DONT_USE_CHRONO ;
}
else
{
result += <library>/boost/chrono//boost_chrono ;
}
result += <library>/boost/chrono//boost_chrono ;
return $(result) ;
}
@ -225,7 +211,7 @@ alias thread_sources
explicit thread_sources ;
lib boost_thread
: thread_sources future.cpp
: thread_sources future.cpp shared_mutex.cpp
: <conditional>@requirements
:
: <link>shared:<define>BOOST_THREAD_USE_DLL=1

View File

@ -30,7 +30,6 @@ New Features:
* [@http://svn.boost.org/trac/boost/ticket/6672 #6672] upgrade_lock:: missing constructors from time related types.
* [@http://svn.boost.org/trac/boost/ticket/6675 #6675] upgrade_lock:: missing non-member swap.
Fixed Bugs:
* [@http://svn.boost.org/trac/boost/ticket/2575 #2575] Bug- Boost 1.36.0 on Itanium platform.
@ -185,11 +184,6 @@ The following features will be included in next releases.
* [@http://svn.boost.org/trac/boost/ticket/6270 #6270] Add thread constructor from movable callable and movable arguments following C++11.
# Add the shared locking upward conversions.
* [@http://svn.boost.org/trac/boost/ticket/6217 #6217] Enhance Boost.Thread shared mutex interface following Howard Hinnant proposal.
# Try to fix the thread specific storage issues.
[endsect]

View File

@ -91,17 +91,17 @@
[table Compliance with Howard's Shared Locking proposal
[[Section] [Description] [Status] [Comments]]
[[X] [Shared Locking] [Partial] [Missing some upwards conversions]]
[[X.1] [Shared Lockables Concepts] [Partial] [ - ]]
[[X.1.1] [SharedLockable concept] [Yes] [ Missing some upwards ownership conversions ]]
[[X.1.2] [UpgradeLockable concept] [Yes] [ Missing some upwards ownership conversions ]]
[[X] [Shared Locking] [Yes] [Needs BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION]]
[[X.1] [Shared Lockables Concepts] [Yes] [ - ]]
[[X.1.1] [SharedLockable concept] [Yes] [ - ]]
[[X.1.2] [UpgradeLockable concept] [Yes] [ - ]]
[[X.2] [Shared Mutex Types] [Yes] [ - ]]
[[X.2.1] [shared_mutex class] [Partial] [ Missing some upwards ownership conversions ]]
[[X.2.2] [upgrade_mutex class] [Partial] [ Missing some upwards ownership conversions ]]
[[X.3] [Locks] [Partial] [Missing some timed conversions]]
[[X.3.1] [unique_lock class adaptations] [Partial] [Missing some upwards conversions]]
[[X.2.1] [shared_mutex class] [Yes] [ - ]]
[[X.2.2] [upgrade_mutex class] [Yes] [ - ]]
[[X.3] [Locks] [Yes] [-]]
[[X.3.1] [unique_lock class adaptations] [Yes] [-]]
[[X.3.2] [shared_lock class] [Yes] [ - ]]
[[X.3.3] [upgrade_lock class] [Partial] [Missing some upwards conversions]]
[[X.3.3] [upgrade_lock class] [Yes] [-]]
]
[endsect]

138
doc/configuration.qbk Normal file
View File

@ -0,0 +1,138 @@
[/
(C) Copyright 20012 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).
]
[section:configuration Configuration]
[section:system Boost.System]
Boost.Thread uses by default Boost.System to define the exceptions. For backward compatibility and also for compilers that don't work well with Boost.System the user can define `BOOST_THREAD_DONT_USE_SYSTEM `.
`BOOST_THREAD_DONT_USE_MOVE` is defined when Boost.Thread uses Boost.Move.
[endsect]
[section:chrono Boost.Chrono]
Boost.Thread uses by default Boost.Chrono for the time related functions. For backward compatibility and also for compilers that don't work well with Boost.Chrono the user can define `BOOST_THREAD_DONT_USE_CHRONO`. If `BOOST_THREAD_DONT_USE_SYSTEM` is defined then `BOOST_THREAD_DONT_USE_CHRONO` is defined implicitly.
`BOOST_THREAD_USE_CHRONO` is defined when Boost.Thread uses Boost.Move.
[endsect]
[section:move Boost.Move]
Boost.Thread uses by default Boost.Move emulation on compilers that don't support Rvalue references. For backward compatibility and also for compilers that don't work well with Boost.Move the user can define `BOOST_THREAD_DONT_USE_MOVE`.
`BOOST_THREAD_USE_MOVE` is defined when Boost.Thread uses Boost.Move.
[endsect]
[section:shared_gen Shared Locking Generic]
The shared mutex implementation on Windows platform provides currently less functionality than the generic one that is used for PTheads based platforms. In order to have access to these functions, the user needs to define `BOOST_THREAD_SHARED_MUTEX_GENERIC` to use the generic implementation, that while could be less efficient, provides all the functions.
[endsect]
[section:shared_upwards Shared Locking Upwards Conversion]
Boost.Threads includes in version 2 the Shared Locking Upwards Conversion as defined in [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking].
These conversions need to be used carefully to avoid deadlock or livelock. The user need to define explicitly `BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION` to get these upwards conversions.
[endsect]
[section:explicit_cnv Explicit Lock Conversion]
In [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking] the lock conversions are explicit. As this explicit conversion breaks the lock interfaces, it is provided only if the `BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION` is defined.
[endsect]
[section:deprecated Deprecated]
Version 2.0.0 deprecates some Boost.Thread features.
These deprecated features will be provided by default up to boost 1.52. If you don't want to include the deprecated features you could define `BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V2_0_0`. Since 1.53 these features will not be included any more by default. Since this version, if you want to include the deprecated features yet you could define `BOOST_THREAD_PROVIDE_DEPRECATED_FEATURES_SINCE_V2_0_0`. These deprecated features will be only available until boost 1.55, that is you have 1 year and a half to move to the new features.
[endsect]
[section:future unique_future versus future]
C++11 uses `std::future`. Versions of Boost.Thread previous to version 2.0.0 uses `boost:unique_future`.
Since version 2.0.0 `boost::future` replaces `boost::__unique_future` when `BOOST_THREAD_USES_FUTURE` is defined. The documentation doesn't contains anymore however `boost::__unique_future`.
[endsect]
[section:lazy promise lazy initialization]
C++11 promise initialize the associated state at construction time. Versions of Boost.Thread previous to version 2.0.0 initialize it lazily at any point in time in which this associated state is needed.
Since version 2.0.0 this difference in behavior can be configured. When `BOOST_THREAD_PROMISE_LAZY` is defined the backward compatible behavior is provided.
[endsect]
[section:alloc promise Allocator constructor]
C++11 std::promise provides constructors with allocators.
template <typename R>
class promise
{
public:
template <class Allocator>
explicit promise(allocator_arg_t, Allocator a);
// ...
};
template <class R, class Alloc> struct uses_allocator<promise<R>,Alloc>: true_type {};
where
struct allocator_arg_t { };
constexpr allocator_arg_t allocator_arg = allocator_arg_t();
template <class T, class Alloc> struct uses_allocator;
Since version 2.0.0 Boost.Thread implements this constructor using the following interface
namespace boost
{
typedef container::allocator_arg_t allocator_arg_t;
constexpr allocator_arg_t allocator_arg = {};
namespace container
{
template <class R, class Alloc>
struct uses_allocator<promise<R>,Alloc>: true_type {};
}
template <class T, class Alloc>
struct uses_allocator : public container::uses_allocator<T, Alloc> {};
}
which introduces a dependency on Boost.Container. This feature is provided only if `BOOST_THREAD_FUTURE_USES_ALLOCATORS` is defined.
[endsect]
[section:version `BOOST_THREAD_VERSION` Version]
`BOOST_THREAD_VERSION` defines the Boost.Thread version.
The default version is 1.
The user can request the version 2 by defining `BOOST_THREAD_VERSION` to 2. In this case the following breaking or extending macros are defined
* Breaking change `BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION `
* Breaking change `BOOST_THREAD_USES_FUTURE`
* Uniformity `BOOST_THREAD_SHARED_MUTEX_GENERIC`
* Extension `BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION`
* Extension `BOOST_THREAD_FUTURE_USES_ALLOCATORS`
[endsect]
[endsect]

View File

@ -758,6 +758,8 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
[[Throws:] [Nothing.]]
[[Notes:] [Available only if BOOST_THREAD_FUTURE_USES_ALLOCATORS is defined.]]
]
[endsect]

View File

@ -358,13 +358,7 @@ A type `L` meets the __SharedLockable requirements if it meets the __TimedLockab
* `m.__try_lock_upgrade()`
* `m.__try_lock_upgrade_for(rel_time)`
* `m.__try_lock_upgrade_until(abs_time)`
* `m.__try_unlock_shared_and_lock()`
* `m.__try_unlock_shared_and_lock_for(rel_time)`
* `m.__try_unlock_shared_and_lock_until(abs_time)`
* `m.__unlock_and_lock_shared()`
* `m.__try_unlock_shared_and_lock_upgrade();`
* `m.__try_unlock_shared_and_lock_upgrade_for(rel_time);`
* `m.__try_unlock_shared_and_lock_upgrade_until(abs_time);`
* `m.__unlock_and_lock_upgrade();`
* `m.__unlock_upgrade_and_lock();`]
* `m.__try_unlock_upgrade_and_lock()`
@ -372,6 +366,17 @@ A type `L` meets the __SharedLockable requirements if it meets the __TimedLockab
* `m.__try_unlock_upgrade_and_lock_until(abs_time)`
* `m.__unlock_upgrade_and_lock_shared();`
If BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION is defined the following expressions are also required:
* `m.__try_unlock_shared_and_lock();`
* `m.__try_unlock_shared_and_lock_for(rel_time);`
* `m.__try_unlock_shared_and_lock_until(abs_time);`
* `m.__try_unlock_shared_and_lock_upgrade();`
* `m.__try_unlock_shared_and_lock_upgrade_for(rel_time);`
* `m.__try_unlock_shared_and_lock_upgrade_until(abs_time);`
Lock ownership acquired through a call to __lock_upgrade_ref__ must be released through a call to __unlock_upgrade_ref__. If the
ownership type is changed through a call to one of the `unlock_xxx_and_lock_yyy()` functions, ownership must be released through a
call to the unlock function corresponding to the new level of ownership.
@ -450,6 +455,8 @@ The function returns within the timeout specified by `rel_time` only if it has o
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -471,6 +478,8 @@ The function returns before the absolute timeout specified by `abs_time` only if
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -489,10 +498,13 @@ If the conversion is not successful, the shared ownership of m is retained.]]
[[Postcondition:] [If the call returns `true`, the current thread has exclusive ownership of `m`.]]
[[Synchronization:] [If `__ try_unlock_shared_and_lock()` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]]
[[Synchronization:] [If `__try_unlock_shared_and_lock()` returns true, prior `__unlock()` and subsequent lock operations on the same object synchronize with this operation. ]]
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -517,6 +529,8 @@ If the conversion is not successful, the shared ownership of the mutex is retain
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -541,6 +555,8 @@ If the conversion is not successful, the shared ownership of the mutex is retain
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -579,6 +595,8 @@ If the conversion is not successful, the shared ownership of the mutex is retain
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -604,6 +622,9 @@ If the conversion is not successful, the shared ownership of m is retained.]]
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -627,6 +648,8 @@ If the conversion is not successful, the shared ownership of the mutex is retain
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -685,6 +708,9 @@ If the conversion is not successful, the upgrade ownership of m is retained.]]
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -709,6 +735,8 @@ If the conversion is not successful, the upgrade ownership of m is retained.]]
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -732,6 +760,8 @@ If the conversion is not successful, the upgrade ownership of m is retained.]]
[[Throws:] [Nothing]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
@ -885,8 +915,18 @@ object passed to the constructor.]]
unique_lock(Lockable& m_,adopt_lock_t);
unique_lock(Lockable& m_,defer_lock_t) noexcept;
unique_lock(Lockable& m_,try_to_lock_t);
unique_lock(Lockable& m_,system_time const& target_time); // DEPRECATED V2
#ifdef BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION
unique_lock(shared_lock<mutex_type>&& sl, try_to_lock_t)
template <class Clock, class Duration>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& rel_time)
#endif
unique_lock(Lockable& m_,system_time const& target_time); // DEPRECATED V2
template <class Clock, class Duration>
unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t);
template <class Rep, class Period>
@ -1016,6 +1056,82 @@ returns `false`.]]
[endsect]
[section:constructor_sh_try `unique_lock(shared_lock<mutex_type>&& sl, try_to_lock_t)`]
[variablelist
[[Requires:] [The supplied `Mutex` type must implement `__try_unlock_shared_and_lock()`.]]
[[Effects:] [Constructs an object of type __unique_lock. Let `pm` be and `owns` the ownership state. Initializes `pm` with nullptr and `owns` with false.
If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.release()`.
Else `sl.__owns_lock()` returns `true`, and in this case if `sl.mutex()->try_unlock_shared_and_lock()` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
[[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()->try_unlock_shared_and_lock()` returns `false`, `sl` is not modified.]]
[[Throws:] [Nothing.]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
[section:constructor_sh_until `unique_lock(shared_lock<mutex_type>&&, const chrono::time_point<Clock, Duration>&)`]
template <class Clock, class Duration>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& abs_time);
[variablelist
[[Requires:] [The supplied `Mutex` type shall implement `__try_unlock_shared_and_lock_until(abs_time)`.]]
[[Effects:] [Constructs an object of type `__unique_lock`, initializing `pm` with `nullptr` and `owns` with `false`.
If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.__release()`.
Else `sl.owns_lock()` returns `true`, and in this case if `sl.mutex()->__try_unlock_shared_and_lock_until(abs_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
[[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()-> __try_unlock_shared_and_lock_until(abs_time)` returns `false`, `sl` is not modified.]]
[[Throws:] [Nothing.]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
[section:constructor_sh_for `unique_lock(shared_lock<mutex_type>&&, const chrono::duration<Rep, Period>&)`]
template <class Rep, class Period>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& rel_time)
[variablelist
[[Requires:] [The supplied `Mutex` type shall implement `__try_unlock_shared_and_lock_for(rel_time)`.]]
[[Effects:] [Constructs an object of type `__unique_lock`, initializing `pm` with `nullptr` and `owns` with `false`.
If `sl.__owns_lock()` returns `false`, sets `pm` to the return value of `sl.__release()`.
Else `sl.owns_lock()` returns `true`, and in this case if `sl.mutex()-> __try_unlock_shared_and_lock_for(rel_time)` returns `true`, sets `pm` to the value returned by `sl.release()` and sets `owns` to `true`.]]
[[Note:] [If `sl.owns_lock()` returns `true` and `sl.mutex()-> __try_unlock_shared_and_lock_for(rel_time)` returns `false`, `sl` is not modified.]]
[[Postcondition:] [.]]
[[Throws:] [Nothing.]]
[[Notes:] [Available only if BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION and BOOST_THREAD_SHARED_MUTEX_GENERIC is defined on Windows platform]]
]
[endsect]
[section:constructor_abs_time `unique_lock(Lockable & m,boost::system_time const& abs_time)` // DEPRECATED V2]
[variablelist
@ -1154,6 +1270,8 @@ __owns_lock_ref__ returns `false`.]]
{
public:
typedef Lockable mutex_type;
// Shared locking
shared_lock();
explicit shared_lock(Lockable& m_);
shared_lock(Lockable& m_,adopt_lock_t);
@ -1170,11 +1288,7 @@ __owns_lock_ref__ returns `false`.]]
shared_lock& operator=(shared_lock const&) = delete;
shared_lock(shared_lock<Lockable> && other);
explicit shared_lock(unique_lock<Lockable> && other);
explicit shared_lock(upgrade_lock<Lockable> && other);
shared_lock& operator=(shared_lock<Lockable> && other);
void swap(shared_lock& other);
void lock();
bool try_lock();
@ -1185,8 +1299,20 @@ __owns_lock_ref__ returns `false`.]]
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock();
// Conversion from upgrade locking
explicit shared_lock(upgrade_lock<Lockable> && other);
// Conversion from exclusive locking
explicit shared_lock(unique_lock<Lockable> && other);
// Setters
void swap(shared_lock& other);
mutex_type* release() noexcept;
// Getters
explicit operator bool() const;
bool owns_lock() const;
mutex_type mutex() const;
};
Like __unique_lock__, __shared_lock__ models the __lockable_concept__, but rather than acquiring unique ownership of the supplied
@ -1382,20 +1508,28 @@ __owns_lock_shared_ref__ returns `false`.]]
{
public:
typedef Lockable mutex_type;
explicit upgrade_lock(Lockable& m_);
upgrade_lock(upgrade_lock<Lockable> && other);
explicit upgrade_lock(unique_lock<Lockable> && other);
// Upgrade locking
upgrade_lock();
explicit upgrade_lock(mutex_type& m_);
upgrade_lock(mutex_type& m, defer_lock_t) noexcept;
upgrade_lock(mutex_type& m, try_to_lock_t);
upgrade_lock(mutex_type& m, adopt_lock_t);
template <class Clock, class Duration>
upgrade_lock(mutex_type& m,
const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
upgrade_lock(mutex_type& m,
const chrono::duration<Rep, Period>& rel_time);
~upgrade_lock();
upgrade_lock(const upgrade_lock& other) = delete;
upgrade_lock& operator=(const upgrade_lock<Lockable> & other) = delete;
upgrade_lock(upgrade_lock<Lockable> && other);
upgrade_lock& operator=(upgrade_lock<Lockable> && other);
void swap(upgrade_lock& other);
void lock();
bool try_lock();
template <class Rep, class Period>
@ -1404,8 +1538,28 @@ __owns_lock_shared_ref__ returns `false`.]]
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock();
#ifdef BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION
// Conversion from shared locking
upgrade_lock(shared_lock<mutex_type>&& sl, try_to_lock_t);
template <class Clock, class Duration>
upgrade_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
upgrade_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& rel_time);
#endif
// Conversion from exclusive locking
explicit upgrade_lock(unique_lock<Lockable> && other);
// Setters
void swap(upgrade_lock& other);
mutex_type* release() noexcept;
// Getters
explicit operator bool() const;
bool owns_lock() const;
mutex_type mutex() const;
};
Like __unique_lock__, __upgrade_lock__ models the __lockable_concept__, but rather than acquiring unique ownership of the supplied
@ -1421,7 +1575,7 @@ pointer to `m` and __owns_lock_ref__ returns `true`. If an object that ['owns] t
is destroyed, then the destructor will invoke [unlock_upgrade_ref_link `mutex()->unlock_upgrade()`].
The member functions of __upgrade_lock__ are not thread-safe. In particular, __upgrade_lock__ is intended to model the upgrade
ownership of a __lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock
ownership of a __upgrade_lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock
state (including the destructor) must be called by the same thread that acquired ownership of the lock state.
[endsect]

View File

@ -20,8 +20,8 @@ closely follow the proposals presented to the C++ Standards Committee, in partic
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2139.html N2139], and
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2094.html N2094]
Vicente J. Botet Escriba started in version 2 the adaptation to comply with the accepted Thread C++11 library (Make use of Boost.Chrono and Boost.Move) and the [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking] Howard Hinnant proposal except for the upward conversions. Some minor features have been added also
as thread attributes, reverse_lock, shared_lock_guard.
Vicente J. Botet Escriba started in version 2 the adaptation to comply with the accepted Thread C++11 library (Make use of Boost.Chrono and Boost.Move) and the [@http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html Shared Locking] Howard Hinnant proposal except for the upward conversions.
Some minor features have been added also as thread attributes, reverse_lock, shared_lock_guard.
In order to use the classes and functions described here, you can
either include the specific headers specified by the descriptions of
@ -42,5 +42,10 @@ The definition of these macros determines whether BOOST_THREAD_USE_DLL is define
The source code compiled when building the library defines a macros BOOST_THREAD_SOURCE that is used to import or export it. The user must not define this macro in any case.
The following section describes all the macros used to configure Boost.Thread.
[include configuration.qbk]
[endsect]

14
doc/sync_tutorial.qbk Normal file
View File

@ -0,0 +1,14 @@
[/
(C) Copyright 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).
]
[section:tutorial Tutorial]
[@http://home.roadrunner.com/~hinnant/mutexes/locking.html Handling mutexes in C++] is an excellent tutorial. You need just replace std and ting by boost.
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html Mutex, Lock, Condition Variable Rationale] adds rationale for the design decisions made for mutexes, locks and condition variables.
[endsect]

View File

@ -6,7 +6,7 @@
http://www.boost.org/LICENSE_1_0.txt).
]
[article Thread
[library Thread
[quickbook 1.5]
[version 2.0.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
@ -222,6 +222,7 @@
[include thread_ref.qbk]
[section:synchronization Synchronization]
[include sync_tutorial.qbk]
[include mutex_concepts.qbk]
[include mutexes.qbk]
[include condition_variables.qbk]

View File

@ -5,6 +5,7 @@
#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_SHARED_MUTEX_GENERIC
#include <iostream>
#include <boost/thread/mutex.hpp>

View File

@ -640,6 +640,181 @@ namespace boost
#endif
#endif
#ifdef BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION
#ifndef BOOST_NO_RVALUE_REFERENCES
// Conversion from shared locking
unique_lock(shared_lock<mutex_type>&& 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 <class Clock, class Duration>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& 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 <class Rep, class Period>
unique_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& 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<shared_lock<mutex_type> >& 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 <class Clock, class Duration>
unique_lock(boost::rv<shared_lock<mutex_type> >& sl,
const chrono::time_point<Clock, Duration>& 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 <class Rep, class Period>
unique_lock(boost::rv<shared_lock<mutex_type> >& sl,
const chrono::duration<Rep, Period>& 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<shared_lock<mutex_type> > 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 <class Clock, class Duration>
unique_lock(detail::thread_move_t<shared_lock<mutex_type> > sl,
const chrono::time_point<Clock, Duration>& 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 <class Rep, class Period>
unique_lock(detail::thread_move_t<shared_lock<mutex_type> > sl,
const chrono::duration<Rep, Period>& 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 @@ namespace boost
public:
typedef Mutex mutex_type;
shared_lock():
shared_lock() BOOST_NOEXCEPT:
m(0),is_locked(false)
{}
@ -848,7 +1023,7 @@ namespace boost
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 @@ namespace boost
#endif
#ifndef BOOST_NO_RVALUE_REFERENCES
shared_lock(shared_lock<Mutex> && other):
shared_lock(shared_lock<Mutex> && other) BOOST_NOEXCEPT:
m(other.m),is_locked(other.is_locked)
{
other.is_locked=false;
@ -906,7 +1081,7 @@ namespace boost
}
shared_lock& operator=(shared_lock<Mutex> && other)
shared_lock& operator=(shared_lock<Mutex> && other) BOOST_NOEXCEPT
{
shared_lock temp(::boost::move(other));
swap(temp);
@ -930,7 +1105,7 @@ namespace boost
#endif
#else
#if defined BOOST_THREAD_USES_MOVE
shared_lock(boost::rv<shared_lock<Mutex> >& other):
shared_lock(boost::rv<shared_lock<Mutex> >& other) BOOST_NOEXCEPT:
m(other.m),is_locked(other.is_locked)
{
other.is_locked=false;
@ -959,24 +1134,24 @@ namespace boost
other.m=0;
}
operator ::boost::rv<shared_lock<Mutex> >&()
operator ::boost::rv<shared_lock<Mutex> >&() BOOST_NOEXCEPT
{
return *static_cast< ::boost::rv<shared_lock<Mutex> >* >(this);
}
operator const ::boost::rv<shared_lock<Mutex> >&() const
operator const ::boost::rv<shared_lock<Mutex> >&() const BOOST_NOEXCEPT
{
return *static_cast<const ::boost::rv<shared_lock<Mutex> >* >(this);
}
::boost::rv<shared_lock<Mutex> >& move()
::boost::rv<shared_lock<Mutex> >& move() BOOST_NOEXCEPT
{
return *static_cast< ::boost::rv<shared_lock<Mutex> >* >(this);
}
const ::boost::rv<shared_lock<Mutex> >& move() const
const ::boost::rv<shared_lock<Mutex> >& move() const BOOST_NOEXCEPT
{
return *static_cast<const ::boost::rv<shared_lock<Mutex> >* >(this);
}
shared_lock& operator=(::boost::rv<shared_lock<Mutex> >& other)
shared_lock& operator=(::boost::rv<shared_lock<Mutex> >& other) BOOST_NOEXCEPT
{
shared_lock temp(other);
swap(temp);
@ -1000,7 +1175,7 @@ namespace boost
#endif
#else
shared_lock(detail::thread_move_t<shared_lock<Mutex> > other):
shared_lock(detail::thread_move_t<shared_lock<Mutex> > other) BOOST_NOEXCEPT:
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
@ -1029,18 +1204,18 @@ namespace boost
other->m=0;
}
operator detail::thread_move_t<shared_lock<Mutex> >()
operator detail::thread_move_t<shared_lock<Mutex> >() BOOST_NOEXCEPT
{
return move();
}
detail::thread_move_t<shared_lock<Mutex> > move()
detail::thread_move_t<shared_lock<Mutex> > move() BOOST_NOEXCEPT
{
return detail::thread_move_t<shared_lock<Mutex> >(*this);
}
shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other)
shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other) BOOST_NOEXCEPT
{
shared_lock temp(other);
swap(temp);
@ -1065,13 +1240,13 @@ namespace boost
#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 @@ namespace boost
#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
typedef void (shared_lock<Mutex>::*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 @@ namespace boost
{};
#endif
template<typename Mutex>
void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs)
void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) BOOST_NOEXCEPT
{
lhs.swap(rhs);
}
@ -1241,7 +1417,7 @@ namespace boost
#endif
public:
typedef Mutex mutex_type;
upgrade_lock():
upgrade_lock() BOOST_NOEXCEPT:
m(0),is_locked(false)
{}
@ -1253,7 +1429,7 @@ namespace boost
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 @@ namespace boost
#endif
#ifndef BOOST_NO_RVALUE_REFERENCES
upgrade_lock(upgrade_lock<Mutex>&& other):
upgrade_lock(upgrade_lock<Mutex>&& other) BOOST_NOEXCEPT:
m(other.m),is_locked(other.is_locked)
{
other.is_locked=false;
@ -1294,7 +1470,7 @@ namespace boost
other.m=0;
}
upgrade_lock& operator=(upgrade_lock<Mutex>&& other)
upgrade_lock& operator=(upgrade_lock<Mutex>&& other) BOOST_NOEXCEPT
{
upgrade_lock temp(::boost::move(other));
swap(temp);
@ -1311,7 +1487,7 @@ namespace boost
#endif
#else
#if defined BOOST_THREAD_USES_MOVE
upgrade_lock(boost::rv<upgrade_lock<Mutex> >& other):
upgrade_lock(boost::rv<upgrade_lock<Mutex> >& other) BOOST_NOEXCEPT:
m(other.m),is_locked(other.is_locked)
{
other.is_locked=false;
@ -1329,23 +1505,23 @@ namespace boost
other.m=0;
}
operator ::boost::rv<upgrade_lock>&()
operator ::boost::rv<upgrade_lock>&() BOOST_NOEXCEPT
{
return *static_cast< ::boost::rv<upgrade_lock>* >(this);
}
operator const ::boost::rv<upgrade_lock>&() const
operator const ::boost::rv<upgrade_lock>&() const BOOST_NOEXCEPT
{
return *static_cast<const ::boost::rv<upgrade_lock>* >(this);
}
::boost::rv<upgrade_lock>& move()
::boost::rv<upgrade_lock>& move() BOOST_NOEXCEPT
{
return *static_cast< ::boost::rv<upgrade_lock>* >(this);
}
const ::boost::rv<upgrade_lock>& move() const
const ::boost::rv<upgrade_lock>& move() const BOOST_NOEXCEPT
{
return *static_cast<const ::boost::rv<upgrade_lock>* >(this);
}
upgrade_lock& operator=(boost::rv<upgrade_lock<Mutex> >& other)
upgrade_lock& operator=(boost::rv<upgrade_lock<Mutex> >& other) BOOST_NOEXCEPT
{
upgrade_lock temp(other);
swap(temp);
@ -1361,7 +1537,7 @@ namespace boost
}
#endif
#else
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other) BOOST_NOEXCEPT:
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
@ -1379,18 +1555,18 @@ namespace boost
other->m=0;
}
operator detail::thread_move_t<upgrade_lock<Mutex> >()
operator detail::thread_move_t<upgrade_lock<Mutex> >() BOOST_NOEXCEPT
{
return move();
}
detail::thread_move_t<upgrade_lock<Mutex> > move()
detail::thread_move_t<upgrade_lock<Mutex> > move() BOOST_NOEXCEPT
{
return detail::thread_move_t<upgrade_lock<Mutex> >(*this);
}
upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) BOOST_NOEXCEPT
{
upgrade_lock temp(other);
swap(temp);
@ -1408,12 +1584,185 @@ namespace boost
#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<mutex_type>&& 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 <class Clock, class Duration>
upgrade_lock(shared_lock<mutex_type>&& sl,
const chrono::time_point<Clock, Duration>& 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 <class Rep, class Period>
upgrade_lock(shared_lock<mutex_type>&& sl,
const chrono::duration<Rep, Period>& 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<shared_lock<mutex_type> > &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 <class Clock, class Duration>
upgrade_lock(boost::rv<shared_lock<mutex_type> > &sl,
const chrono::time_point<Clock, Duration>& 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 <class Rep, class Period>
upgrade_lock(boost::rv<shared_lock<mutex_type> > &sl,
const chrono::duration<Rep, Period>& 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<shared_lock<mutex_type> > 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 <class Clock, class Duration>
upgrade_lock(detail::thread_move_t<shared_lock<mutex_type> > sl,
const chrono::time_point<Clock, Duration>& 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 <class Rep, class Period>
upgrade_lock(detail::thread_move_t<shared_lock<mutex_type> >& sl,
const chrono::duration<Rep, Period>& 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 @@ namespace boost
#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 @@ namespace boost
}
#ifndef BOOST_NO_RVALUE_REFERENCES
upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex>&& other):
upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex>&& other) BOOST_NOEXCEPT:
source(other.source),exclusive(::boost::move(other.exclusive))
{
other.source=0;
}
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Mutex>&& other)
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Mutex>&& other) BOOST_NOEXCEPT
{
upgrade_to_unique_lock temp(other);
swap(temp);
@ -1619,59 +1968,59 @@ namespace boost
}
#else
#if defined BOOST_THREAD_USES_MOVE
upgrade_to_unique_lock(boost::rv<upgrade_to_unique_lock<Mutex> >& other):
upgrade_to_unique_lock(boost::rv<upgrade_to_unique_lock<Mutex> >& other) BOOST_NOEXCEPT:
source(other.source),exclusive(::boost::move(other.exclusive))
{
other.source=0;
}
upgrade_to_unique_lock& operator=(boost::rv<upgrade_to_unique_lock<Mutex> >& other)
upgrade_to_unique_lock& operator=(boost::rv<upgrade_to_unique_lock<Mutex> >& other) BOOST_NOEXCEPT
{
upgrade_to_unique_lock temp(other);
swap(temp);
return *this;
}
operator ::boost::rv<upgrade_to_unique_lock>&()
operator ::boost::rv<upgrade_to_unique_lock>&() BOOST_NOEXCEPT
{
return *static_cast< ::boost::rv<upgrade_to_unique_lock>* >(this);
}
operator const ::boost::rv<upgrade_to_unique_lock>&() const
operator const ::boost::rv<upgrade_to_unique_lock>&() const BOOST_NOEXCEPT
{
return *static_cast<const ::boost::rv<upgrade_to_unique_lock>* >(this);
}
::boost::rv<upgrade_to_unique_lock>& move()
::boost::rv<upgrade_to_unique_lock>& move() BOOST_NOEXCEPT
{
return *static_cast< ::boost::rv<upgrade_to_unique_lock>* >(this);
}
const ::boost::rv<upgrade_to_unique_lock>& move() const
const ::boost::rv<upgrade_to_unique_lock>& move() const BOOST_NOEXCEPT
{
return *static_cast<const ::boost::rv<upgrade_to_unique_lock>* >(this);
}
#else
upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other):
upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other) BOOST_NOEXCEPT:
source(other->source),exclusive(::boost::move(other->exclusive))
{
other->source=0;
}
upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other)
upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other) BOOST_NOEXCEPT
{
upgrade_to_unique_lock temp(other);
swap(temp);
return *this;
}
operator detail::thread_move_t<upgrade_to_unique_lock<Mutex> >()
operator detail::thread_move_t<upgrade_to_unique_lock<Mutex> >() BOOST_NOEXCEPT
{
return move();
}
detail::thread_move_t<upgrade_to_unique_lock<Mutex> > move()
detail::thread_move_t<upgrade_to_unique_lock<Mutex> > move() BOOST_NOEXCEPT
{
return detail::thread_move_t<upgrade_to_unique_lock<Mutex> >(*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 @@ namespace boost
#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();
}

View File

@ -437,6 +437,57 @@ namespace boost
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 <class Rep, class Period>
bool
try_unlock_shared_and_lock_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_shared_and_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);
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 @@ namespace boost
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 <class Rep, class Period>
bool
try_unlock_shared_and_lock_upgrade_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_upgrade_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_upgrade_until(
const chrono::time_point<Clock, Duration>& 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;

328
src/shared_mutex.cpp Normal file
View File

@ -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 <boost/thread/v2/shared_mutex.hpp>
#include <boost/thread/locks.hpp>
namespace boost
{
namespace thread_v2
{
// shared_mutex
shared_mutex::shared_mutex()
: state_(0)
{
}
shared_mutex::~shared_mutex()
{
boost::lock_guard<mutex_t> _(mut_);
}
// Exclusive ownership
void
shared_mutex::lock()
{
boost::unique_lock<mutex_t> 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<mutex_t> lk(mut_);
if (state_ == 0)
{
state_ = write_entered_;
return true;
}
return false;
}
void
shared_mutex::unlock()
{
boost::lock_guard<mutex_t> _(mut_);
state_ = 0;
gate1_.notify_all();
}
// Shared ownership
void
shared_mutex::lock_shared()
{
boost::unique_lock<mutex_t> 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<mutex_t> 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<mutex_t> _(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<mutex_t> _(mut_);
}
// Exclusive ownership
void
upgrade_mutex::lock()
{
boost::unique_lock<mutex_t> 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<mutex_t> lk(mut_);
if (state_ == 0)
{
state_ = write_entered_;
return true;
}
return false;
}
void
upgrade_mutex::unlock()
{
boost::lock_guard<mutex_t> _(mut_);
state_ = 0;
gate1_.notify_all();
}
// Shared ownership
void
upgrade_mutex::lock_shared()
{
boost::unique_lock<mutex_t> 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<mutex_t> 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<mutex_t> _(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<mutex_t> 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<mutex_t> 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<mutex_t> _(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<mutex_t> lk(mut_);
if (state_ == 1)
{
state_ = write_entered_;
return true;
}
return false;
}
void
upgrade_mutex::unlock_and_lock_shared()
{
{
boost::lock_guard<mutex_t> _(mut_);
state_ = 1;
}
gate1_.notify_all();
}
// Shared <-> Upgrade
bool
upgrade_mutex::try_unlock_shared_and_lock_upgrade()
{
boost::unique_lock<mutex_t> 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<mutex_t> _(mut_);
state_ &= ~upgradable_entered_;
}
gate1_.notify_all();
}
// Upgrade <-> Exclusive
void
upgrade_mutex::unlock_upgrade_and_lock()
{
boost::unique_lock<mutex_t> 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<mutex_t> lk(mut_);
if (state_ == (upgradable_entered_ | 1))
{
state_ = write_entered_;
return true;
}
return false;
}
void
upgrade_mutex::unlock_and_lock_upgrade()
{
{
boost::lock_guard<mutex_t> _(mut_);
state_ = upgradable_entered_ | 1;
}
gate1_.notify_all();
}
} // thread_v2
} // boost

View File

@ -10,6 +10,7 @@
// reverse_lock& operator=(reverse_lock const&) = delete;
#include <boost/thread/locks.hpp>
#include <boost/thread/reverse_lock.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/detail/lightweight_test.hpp>
@ -23,7 +24,7 @@ int main()
{
boost::reverse_lock<boost::unique_lock<boost::mutex> > lg0(lk0);
boost::reverse_lock<boost::unique_lock<boost::mutex> > lg1(lk1);
lk1 = lk0;
lg1 = lg0;
}
}

View File

@ -11,6 +11,7 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/reverse_lock.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/detail/lightweight_test.hpp>

View File

@ -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)
// <boost/thread/locks.hpp>
// template <class Mutex> class unique_lock;
// template <class Rep, class Period>
// unique_lock(shared_lock<mutex_type>&&,
// const chrono::duration<Rep, Period>&);
#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_SHARED_MUTEX_GENERIC
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::shared_mutex m;
int main()
{
{
boost::shared_lock<boost::shared_mutex> lk0(m);
boost::unique_lock<boost::shared_mutex> 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<boost::shared_mutex>
lk(boost::shared_lock<boost::shared_mutex>(m), boost::chrono::milliseconds(1));
BOOST_TEST(lk.mutex() == &m);
BOOST_TEST(lk.owns_lock() == true);
}
{
boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock);
boost::unique_lock<boost::shared_mutex> 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<boost::shared_mutex> lk0(m, boost::defer_lock);
lk0.release();
boost::unique_lock<boost::shared_mutex> 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();
}

View File

@ -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)
// <boost/thread/locks.hpp>
// template <class Mutex> 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 <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::shared_mutex m;
int main()
{
{
boost::shared_lock<boost::shared_mutex> lk0(m);
boost::unique_lock<boost::shared_mutex> 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<boost::shared_mutex> lk(boost::shared_lock<boost::shared_mutex>(m), boost::try_to_lock);
BOOST_TEST(lk.mutex() == &m);
BOOST_TEST(lk.owns_lock() == true);
}
{
boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock);
boost::unique_lock<boost::shared_mutex> 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<boost::shared_mutex> lk0(m, boost::defer_lock);
lk0.release();
boost::unique_lock<boost::shared_mutex> 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();
}

View File

@ -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)
// <boost/thread/locks.hpp>
// template <class Mutex> class unique_lock;
// template <class Clock, class Duration>
// unique_lock(shared_lock<mutex_type>&&,
// const chrono::time_point<Clock, Duration>&);
#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_SHARED_MUTEX_GENERIC
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::shared_mutex m;
int main()
{
{
boost::shared_lock<boost::shared_mutex> lk0(m);
boost::unique_lock<boost::shared_mutex> 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<boost::shared_mutex>
lk( boost::shared_lock<boost::shared_mutex>(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1));
BOOST_TEST(lk.mutex() == &m);
BOOST_TEST(lk.owns_lock() == true);
}
{
boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock);
boost::unique_lock<boost::shared_mutex> 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<boost::shared_mutex> lk0(m, boost::defer_lock);
lk0.release();
boost::unique_lock<boost::shared_mutex> 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();
}

View File

@ -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)
// <boost/thread/locks.hpp>
// template <class Mutex> class upgrade_lock;
// template <class Clock, class Duration>
// upgrade_lock(shared_lock<mutex_type>&&,
// const chrono::duration<Rep, Period>&);
#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_SHARED_MUTEX_GENERIC
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::shared_mutex m;
int main()
{
{
boost::shared_lock<boost::shared_mutex> lk0(m);
boost::upgrade_lock<boost::shared_mutex> 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<boost::shared_mutex>
lk(boost::shared_lock<boost::shared_mutex>(m), boost::chrono::milliseconds(1));
BOOST_TEST(lk.mutex() == &m);
BOOST_TEST(lk.owns_lock() == true);
}
{
boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock);
boost::upgrade_lock<boost::shared_mutex> 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<boost::shared_mutex> lk0(m, boost::defer_lock);
lk0.release();
boost::upgrade_lock<boost::shared_mutex> 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();
}

View File

@ -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)
// <boost/thread/locks.hpp>
// template <class Mutex> 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 <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::shared_mutex m;
int main()
{
{
boost::shared_lock<boost::shared_mutex> lk0(m);
boost::upgrade_lock<boost::shared_mutex> 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<boost::shared_mutex> lk(boost::shared_lock<boost::shared_mutex>(m), boost::try_to_lock);
BOOST_TEST(lk.mutex() == &m);
BOOST_TEST(lk.owns_lock() == true);
}
{
boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock);
boost::upgrade_lock<boost::shared_mutex> 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<boost::shared_mutex> lk0(m, boost::defer_lock);
lk0.release();
boost::upgrade_lock<boost::shared_mutex> 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();
}

View File

@ -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)
// <boost/thread/locks.hpp>
// template <class Mutex> class upgrade_lock;
// template <class Clock, class Duration>
// upgrade_lock(shared_lock<mutex_type>&&,
// const chrono::time_point<Clock, Duration>&);
#define BOOST_THREAD_SHARED_MUTEX_PROVIDES_UPWARDS_CONVERSION
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_SHARED_MUTEX_GENERIC
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/detail/lightweight_test.hpp>
boost::shared_mutex m;
int main()
{
{
boost::shared_lock<boost::shared_mutex> lk0(m);
boost::upgrade_lock<boost::shared_mutex> 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<boost::shared_mutex>
lk( boost::shared_lock<boost::shared_mutex>(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1));
BOOST_TEST(lk.mutex() == &m);
BOOST_TEST(lk.owns_lock() == true);
}
{
boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock);
boost::upgrade_lock<boost::shared_mutex> 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<boost::shared_mutex> lk0(m, boost::defer_lock);
lk0.release();
boost::upgrade_lock<boost::shared_mutex> 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();
}