Thread: Added shared mutex upwards conversion + configuration macros
[SVN r77704]
This commit is contained in:
parent
09d5125278
commit
08ed4c4201
@ -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
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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
138
doc/configuration.qbk
Normal 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]
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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
14
doc/sync_tutorial.qbk
Normal 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]
|
@ -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]
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
328
src/shared_mutex.cpp
Normal 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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user