|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r83396 - in trunk: boost/thread boost/thread/detail libs/thread/doc libs/thread/example
From: vicente.botet_at_[hidden]
Date: 2013-03-10 10:55:02
Author: viboes
Date: 2013-03-10 10:54:59 EDT (Sun, 10 Mar 2013)
New Revision: 83396
URL: http://svn.boost.org/trac/boost/changeset/83396
Log:
Thread: Added noexcep to some synchronized_value constructors + doc.
Text files modified:
trunk/boost/thread/detail/config.hpp | 2
trunk/boost/thread/synchronized_value.hpp | 14
trunk/libs/thread/doc/mutex_concepts.qbk | 235 ++++++++++++++++++++++
trunk/libs/thread/doc/mutexes.qbk | 407 ++++++++++++++++++++++++++++++++++++++++
trunk/libs/thread/doc/synchronized_value.qbk | 17 +
trunk/libs/thread/doc/thread.qbk | 1
trunk/libs/thread/example/synchronized_person.cpp | 2
7 files changed, 668 insertions(+), 10 deletions(-)
Modified: trunk/boost/thread/detail/config.hpp
==============================================================================
--- trunk/boost/thread/detail/config.hpp (original)
+++ trunk/boost/thread/detail/config.hpp 2013-03-10 10:54:59 EDT (Sun, 10 Mar 2013)
@@ -88,9 +88,11 @@
#if defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS
+#define BOOST_THREAD_NO_SYNCHRONIZE
#elif defined _MSC_VER && _MSC_VER <= 1600
// C++ features supported by VC++ 10 (aka 2010)
#define BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS
+#define BOOST_THREAD_NO_SYNCHRONIZE
#endif
/// BASIC_THREAD_ID
Modified: trunk/boost/thread/synchronized_value.hpp
==============================================================================
--- trunk/boost/thread/synchronized_value.hpp (original)
+++ trunk/boost/thread/synchronized_value.hpp 2013-03-10 10:54:59 EDT (Sun, 10 Mar 2013)
@@ -25,7 +25,7 @@
//#include <type_traits>
//#endif
-#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
+#if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics.
#include <functional>
#endif
@@ -65,7 +65,7 @@
lk_(mtx), value_(val)
{
}
- const_strict_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t tag) :
+ const_strict_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t tag) BOOST_NOEXCEPT :
lk_(mtx, tag), value_(val)
{
}
@@ -73,7 +73,7 @@
* Move constructor.
* @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
*/
- const_strict_lock_ptr(BOOST_THREAD_RV_REF(const_strict_lock_ptr) other)
+ const_strict_lock_ptr(BOOST_THREAD_RV_REF(const_strict_lock_ptr) other) BOOST_NOEXCEPT
: lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_)
{
}
@@ -479,7 +479,7 @@
* Assignment operator.
*
* Effects: Copies the underlying value on a scope protected by the two mutexes.
- * The mutexes are not copied. The locks are acquired using lock, so deadlock is avoided.
+ * The mutex is not copied. The locks are acquired using lock, so deadlock is avoided.
* For example, there is no problem if one thread assigns a = b and the other assigns b = a.
*
* Return: *this
@@ -697,7 +697,7 @@
deref_value(BOOST_THREAD_RV_REF(deref_value) other):
lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_)
{}
- operator T()
+ operator T&()
{
return value_;
}
@@ -727,7 +727,7 @@
lk_(boost::move(BOOST_THREAD_RV(other).lk_)), value_(BOOST_THREAD_RV(other).value_)
{}
- operator T()
+ operator const T&()
{
return value_;
}
@@ -938,7 +938,7 @@
return is;
}
-#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
+#if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
#if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
template <typename ...SV>
Modified: trunk/libs/thread/doc/mutex_concepts.qbk
==============================================================================
--- trunk/libs/thread/doc/mutex_concepts.qbk (original)
+++ trunk/libs/thread/doc/mutex_concepts.qbk 2013-03-10 10:54:59 EDT (Sun, 10 Mar 2013)
@@ -1134,7 +1134,7 @@
The following classes are models of `StrictLock`:
* strict_lock: ensured by construction,
-* nested_strict_lock: ensured by construction,
+* nested_strict_lock: "sur parolle" as the user could use adopt_lock_t on unique_lock constructor overload without having locked the mutex,
* __lock_guard__: "sur parolle" as the user could use adopt_lock_t constructor overload without having locked the mutex.
[endsect] [/ Models]
@@ -2002,6 +2002,8 @@
{
public:
typedef BasicLockable mutex_type;
+ strict_lock(strict_lock const& m_) = delete;
+ strict_lock& operator=(strict_lock const& m_) = delete;
explicit strict_lock(mutex_type& m_);
~strict_lock();
@@ -2052,6 +2054,8 @@
{
public:
typedef BasicLockable mutex_type;
+ nested_strict_lock(nested_strict_lock const& m_) = delete;
+ nested_strict_lock& operator=(nested_strict_lock const& m_) = delete;
explicit nested_strict_lock(Lock& lk),
~nested_strict_lock() noexcept;
@@ -2154,6 +2158,235 @@
[endsect]
+[section:lock_ptrs Locking pointers]
+
+ // #include <boost/thread/synchroniezd_value.hpp>
+ // #include <boost/thread/strict_lock_ptr.hpp>
+
+ namespace boost
+ {
+
+ template<typename T, typename Lockable = mutex>
+ class strict_lock_ptr;
+ template<typename T, typename Lockable = mutex>
+ class const_strict_lock_ptr;
+ }
+
+
+[/
+ template<typename T, typename Lockable = mutex>
+ class unique_lock_ptr;
+ template<typename T, typename Lockable = mutex>
+ class const_unique_lock_ptr;
+
+]
+
+[section:const_strict_lock_ptr Class template `const_strict_lock_ptr `]
+
+ // #include <boost/thread/synchroniezd_value.hpp>
+ // #include <boost/thread/strict_lock_ptr.hpp>
+
+
+ template <typename T, typename Lockable = mutex>
+ class const_strict_lock_ptr
+ {
+ public:
+ typedef T value_type;
+ typedef Lockable mutex_type;
+
+ const_strict_lock_ptr(const_strict_lock_ptr const& m_) = delete;
+ const_strict_lock_ptr& operator=(const_strict_lock_ptr const& m_) = delete;
+
+ const_strict_lock_ptr(T const& val, Lockable & mtx);
+ const_strict_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t tag);
+
+ ~const_strict_lock_ptr();
+
+ const T* operator->() const;
+ const T& operator*() const;
+
+ };
+
+
+[section:constructor `const_strict_lock_ptr(T const&,Lockable&)`]
+
+
+ const_strict_lock_ptr(T const& val, Lockable & m);
+
+[variablelist
+
+[[Effects:] [Invokes [lock_ref_link `m.lock()`], stores a reference to it and to the value type `val`.]]
+
+[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
+
+]
+
+[endsect]
+[section:constructor_adopt `const_strict_lock_ptr(T const&,Lockable&,adopt_lock_t)`]
+
+ const_strict_lock_ptr(T const& val, Lockable & m, adopt_lock_t tag);
+
+[variablelist
+
+[[Effects:] [Stores a reference to it and to the value type `val`.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[section:destructor `~const_strict_lock_ptr()`]
+
+ ~const_strict_lock_ptr();
+
+[variablelist
+
+[[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__
+object passed to the constructor.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:indir `operator->() const`]
+
+ const T* operator->() const;
+
+
+[variablelist
+
+[[Return:] [return a constant pointer to the protected value.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:deref `operator*() const`]
+
+ const T& operator*() const;
+
+
+[variablelist
+
+[[Return:] [return a constant reference to the protected value.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[endsect] [/ const_strict_lock_ptr ]
+
+[section:strict_lock_ptr Class template `strict_lock_ptr`]
+
+ // #include <boost/thread/synchroniezd_value.hpp>
+ // #include <boost/thread/strict_lock_ptr.hpp>
+
+ template <typename T, typename Lockable = mutex>
+ class strict_lock_ptr : public const_strict_lock_ptr<T,Lockable>
+ {
+ public:
+ strict_lock_ptr(strict_lock_ptr const& m_) = delete;
+ strict_lock_ptr& operator=(strict_lock_ptr const& m_) = delete;
+
+ strict_lock_ptr(T & val, Lockable & mtx);
+ strict_lock_ptr(T & val, Lockable & mtx, adopt_lock_t tag);
+ ~strict_lock_ptr();
+
+ T* operator->();
+ T& operator*();
+
+ };
+
+
+[section:constructor `strict_lock_ptr(T const&,Lockable&)`]
+
+
+ strict_lock_ptr(T const& val, Lockable & m);
+
+[variablelist
+
+[[Effects:] [Invokes [lock_ref_link `m.lock()`], stores a reference to it and to the value type `val`.]]
+
+[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]]
+
+]
+
+[endsect]
+[section:constructor_adopt `strict_lock_ptr(T const&,Lockable&,adopt_lock_t)`]
+
+ strict_lock_ptr(T const& val, Lockable & m, adopt_lock_t tag);
+
+[variablelist
+
+[[Effects:] [Stores a reference to it and to the value type `val`.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[section:destructor `~strict_lock_ptr()`]
+
+ ~ strict_lock_ptr();
+
+[variablelist
+
+[[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__
+object passed to the constructor.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:indir `operator->()`]
+
+ T* operator->();
+
+
+[variablelist
+
+[[Return:] [return a pointer to the protected value.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:deref `operator*()`]
+
+ T& operator*();
+
+
+[variablelist
+
+[[Return:] [return a reference to the protected value.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[endsect] [/ strict_lock_ptr ]
+
+[endsect] [/ lock_ptrs ]
+
+
[section Externally Locked]
// #include <boost/thread/externally_locked.hpp>
Modified: trunk/libs/thread/doc/mutexes.qbk
==============================================================================
--- trunk/libs/thread/doc/mutexes.qbk (original)
+++ trunk/libs/thread/doc/mutexes.qbk 2013-03-10 10:54:59 EDT (Sun, 10 Mar 2013)
@@ -239,3 +239,410 @@
[include shared_mutex_ref.qbk]
[endsect]
+
+[section:synchronized_value_ref Synchronized Values]
+
+
+ namespace boost
+ {
+
+ template<typename T, typename Lockable = mutex>
+ class synchronized_value;
+
+ // Specialized swap algorithm
+ template <typename T, typename L>
+ void swap(synchronized_value<T,L> & lhs, synchronized_value<T,L> & rhs);
+ template <typename T, typename L>
+ void swap(synchronized_value<T,L> & lhs, T & rhs);
+ template <typename T, typename L>
+ void swap(T & lhs, synchronized_value<T,L> & rhs);
+
+ // Hash support
+ template<typename T, typename L>
+ struct hash<synchronized_value<T,L> >;
+
+ // Comparison
+ template <typename T, typename L>
+ bool operator==(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
+ template <typename T, typename L>
+ bool operator!=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
+ template <typename T, typename L>
+ bool operator<(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
+ template <typename T, typename L>
+ bool operator<=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
+ template <typename T, typename L>
+ bool operator>(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
+ template <typename T, typename L>
+ bool operator>=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
+
+ // Comparison with T
+ template <typename T, typename L>
+ bool operator==(T const& lhs, synchronized_value<T,L> const&rhs);
+ template <typename T, typename L>
+ bool operator!=(T const& lhs, synchronized_value<T,L> const&rhs);
+ template <typename T, typename L>
+ bool operator<(T const& lhs, synchronized_value<T,L> const&rhs);
+ template <typename T, typename L>
+ bool operator<=(T const& lhs, synchronized_value<T,L> const&rhs);
+ template <typename T, typename L>
+ bool operator>(T const& lhs, synchronized_value<T,L> const&rhs);
+ template <typename T, typename L>
+ bool operator>=(T const& lhs, synchronized_value<T,L> const&rhs);
+
+ template <typename T, typename L>
+ bool operator==(synchronized_value<T,L> const& lhs, T const& rhs);
+ template <typename T, typename L>
+ bool operator!=(synchronized_value<T,L> const& lhs, T const& rhs);
+ template <typename T, typename L>
+ bool operator<(synchronized_value<T,L> const& lhs, T const& rhs);
+ template <typename T, typename L>
+ bool operator<=(synchronized_value<T,L> const& lhs, T const& rhs);
+ template <typename T, typename L>
+ bool operator>(synchronized_value<T,L> const& lhs, T const& rhs);
+ template <typename T, typename L>
+ bool operator>=(synchronized_value<T,L> const& lhs, T const& rhs);
+
+ #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
+ template <typename ...SV>
+ std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv);
+ #endif
+ }
+
+[section:synchronized_value Class `synchronized_value`]
+
+ #include <boost/thread/synchronized_value.hpp>
+
+ namespace boost
+ {
+
+ template<typename T, typename Lockable = mutex>
+ class synchronized_value
+ {
+ public:
+ typedef T value_type;
+ typedef Lockable mutex_type;
+
+ synchronized_value() noexept(is_nothrow_default_constructible<T>::value);
+ synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value);
+ synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value);
+ synchronized_value(synchronized_value const& rhs);
+ synchronized_value(synchronized_value&& other);
+
+ // mutation
+ synchronized_value& operator=(synchronized_value const& rhs);
+ synchronized_value& operator=(value_type const& val);
+ void swap(synchronized_value & rhs);
+ void swap(value_type & rhs);
+
+ //observers
+ T get() const;
+ #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+ explicit operator T() const;
+ #endif
+
+ strict_lock_ptr<T,Lockable> operator->();
+ const_strict_lock_ptr<T,Lockable> operator->() const;
+ strict_lock_ptr<T,Lockable> synchronize();
+ const_strict_lock_ptr<T,Lockable> synchronize() const;
+
+ deref_value operator*();;
+ const_deref_value operator*() const;
+
+ private:
+ T value_; // for exposition only
+ mutable mutex_type mtx_; // for exposition only
+ };
+ }
+
+[variablelist
+
+[[Requires:] [`Lockable` is `Lockable`.]]
+
+]
+
+
+[section:constructor `synchronized_value()`]
+
+ synchronized_value() noexept(is_nothrow_default_constructible<T>::value);
+
+[variablelist
+
+[[Requires:] [`T` is `DefaultConstructible`.]]
+[[Effects:] [Default constructs the cloaked value_type]]
+
+[[Throws:] [Any exception thrown by `value_type()`.]]
+
+]
+
+[endsect]
+
+
+[section:constructor_vt `synchronized_value(T const&)`]
+
+ synchronized_value(T const& other) noexept(is_nothrow_copy_constructible<T>::value);
+
+[variablelist
+
+[[Requires:] [`T` is `CopyConstructible`.]]
+[[Effects:] [Copy constructs the cloaked value_type using the parameter `other`]]
+
+[[Throws:] [Any exception thrown by `value_type(other)`.]]
+
+]
+
+[endsect]
+
+[section:copy_cons `synchronized_value(synchronized_value const&)`]
+
+ synchronized_value(synchronized_value const& rhs);
+
+[variablelist
+
+[[Requires:] [`T` is `DefaultConstructible` and `Assignable`.]]
+[[Effects:] [Assigns the value on a scope protected by the mutex of the rhs. The mutex is not copied.]]
+
+[[Throws:] [Any exception thrown by `value_type()` or `value_type& operator=(value_type&)` or `mtx_.lock()`.]]
+
+]
+
+[endsect]
+
+[section:move_vt `synchronized_value(T&&)`]
+
+ synchronized_value(T&& other) noexept(is_nothrow_move_constructible<T>::value);
+
+[variablelist
+
+[[Requires:] [`T` is `CopyMovable `.]]
+[[Effects:] [Move constructs the cloaked value_type]]
+
+[[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
+
+]
+
+[endsect]
+
+[section:move `synchronized_value(synchronized_value&&)`]
+
+ synchronized_value(synchronized_value&& other);
+
+[variablelist
+
+[[Requires:] [`T` is `CopyMovable `.]]
+[[Effects:] [Move constructs the cloaked value_type]]
+
+[[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
+
+]
+
+[endsect]
+
+[section:assign `operator=(synchronized_value const&)`]
+
+ synchronized_value& operator=(synchronized_value const& rhs);
+
+[variablelist
+
+[[Requires:] [`T` is `Assignale`.]]
+[[Effects:] [Copies the underlying value on a scope protected by the two mutexes. The mutex is not copied. The locks are acquired avoiding deadlock. For example, there is no problem if one thread assigns `a = b` and the other assigns `b = a`.]]
+[[Return:] [`*this`]]
+
+[[Throws:] [Any exception thrown by `value_type& operator(value_type const&)` or `mtx_.lock()`.]]
+
+]
+
+[endsect]
+[section:assign_vt `operator=(T const&)`]
+
+ synchronized_value& operator=(value_type const& val);
+
+[variablelist
+
+[[Requires:] [`T` is `Assignale`.]]
+[[Effects:] [Copies the value on a scope protected by the mutex.]]
+[[Return:] [`*this`]]
+
+[[Throws:] [Any exception thrown by `value_type& operator(value_type const&)` or `mtx_.lock()`.]]
+
+]
+
+[endsect]
+
+[section:get `get() const`]
+
+ T get() const;
+
+[variablelist
+
+[[Requires:] [`T` is `CopyConstructible`.]]
+[[Return:] [`A copy of the protected value obtained on a scope protected by the mutex.`]]
+
+[[Throws:] [Any exception thrown by `value_type(value_type const&)` or `mtx_.lock()`.]]
+
+]
+
+[endsect]
+
+
+[section:T `operator T() const`]
+
+ #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+ explicit operator T() const;
+ #endif
+
+[variablelist
+
+[[Requires:] [`T` is `CopyConstructible`.]]
+[[Return:] [`A copy of the protected value obtained on a scope protected by the mutex.`]]
+
+[[Throws:] [Any exception thrown by `value_type(value_type const&)` or `mtx_.lock()`.]]
+
+]
+
+[endsect]
+
+[section:swap `swap(synchronized_value&)`]
+
+ void swap(synchronized_value & rhs);
+
+[variablelist
+
+[[Requires:] [`T` is `Assignale`.]]
+[[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
+
+[[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]
+
+]
+
+[endsect]
+
+[section:swap_vt `swap(synchronized_value&)`]
+
+ void swap(value_type & rhs);
+
+[variablelist
+
+[[Requires:] [`T` is `Swapable`.]]
+[[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
+
+[[Throws:] [Any exception thrown by `swap(value_, rhs)` or `mtx_.lock()`.]]
+
+]
+
+[endsect]
+[section:indir `operator->()`]
+
+ strict_lock_ptr<T,Lockable> operator->();
+
+
+Essentially calling a method `obj->foo(x, y, z)` calls the method `foo(x, y, z)` inside a critical section as long-lived as the call itself.
+
+[variablelist
+
+[[Return:] [`A strict_lock_ptr<>.`]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[section:indir_const `operator->() const`]
+
+ const_strict_lock_ptr<T,Lockable> operator->() const;
+
+
+If the `synchronized_value` object involved is const-qualified, then you'll only be able to call const methods
+through `operator->`. So, for example, `vec->push_back("xyz")` won't work if `vec` were const-qualified.
+The locking mechanism capitalizes on the assumption that const methods don't modify their underlying data.
+
+[variablelist
+
+[[Return:] [`A const_strict_lock_ptr <>.`]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[section:synchronize `synchronize()`]
+
+ strict_lock_ptr<T,Lockable> synchronize();
+
+The synchronize() factory make easier to lock on a scope. As discussed, `operator->` can only lock over the duration of a call, so it is insufficient for complex operations. With `synchronize()` you get to lock the object in a scoped and to directly access the object inside that scope.
+
+[*Example:]
+
+ void fun(synchronized_value<vector<int>> & vec) {
+ auto vec2=vec.synchronize();
+ vec2.push_back(42);
+ assert(vec2.back() == 42);
+ }
+
+[variablelist
+
+[[Return:] [`A strict_lock_ptr <>.`]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[section:synchronize_const `synchronize() const`]
+
+ const_strict_lock_ptr<T,Lockable> synchronize() const;
+
+[variablelist
+
+[[Return:] [`A const_strict_lock_ptr <>.`]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:deref `operator*()`]
+
+ deref_value operator*();;
+
+[variablelist
+
+[[Return:] [`A an instance of a class that locks the mutex on construction and unlocks it on destruction and provides implicit conversion to a reference to the protected value.`]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+[section:deref_const `operator*() const`]
+
+ const_deref_value operator*() const;
+
+
+[variablelist
+
+[[Return:] [`A an instance of a class that locks the mutex on construction and unlocks it on destruction and provides implicit conversion to a constant reference to the protected value.`]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+
+
+[endsect]
+[section:synchronize Non-Member Function `synchronize`]
+
+ #include <boost/thread/synchronized_value.hpp>
+ namespace boost
+ {
+ #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
+ template <typename ...SV>
+ std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv);
+ #endif
+ }
+
+[endsect]
+[endsect]
Modified: trunk/libs/thread/doc/synchronized_value.qbk
==============================================================================
--- trunk/libs/thread/doc/synchronized_value.qbk (original)
+++ trunk/libs/thread/doc/synchronized_value.qbk 2013-03-10 10:54:59 EDT (Sun, 10 Mar 2013)
@@ -108,12 +108,27 @@
}
}
+While the preceding takes care of dead-lock, the access to the synchronized_value via unique_lock_ptr requires a lock that is not forced by the interface.
+An alternative on compilers providing a standard library that supports movable std::tuple is to use the free synchronize function, which will lock all the mutexes associated to the synchronized values and return a tuple os strict_lock_ptr.
+
+ synchronized_value<std::queue<MessageType> > q1,q2;
+ void transferMessage()
+ {
+ auto lks = synchronize(u1,u2); // dead-lock free algorithm
+
+ if(!std::get<1>(lks)->empty())
+ {
+ std::get<2>(lks)->push_back(u1->front());
+ std::get<1>(lks)->pop_front();
+ }
+ }
+
[endsect] [/Operations Across Multiple Objects]
[section Value semantics]
-synchronized_value has value semantics even if the syntax let it appear as a pointer.
+synchronized_value has value semantics even if the syntax lets is close to a pointer (this is just because we are unable to define smart references).
[endsect] [/Value semantics]
Modified: trunk/libs/thread/doc/thread.qbk
==============================================================================
--- trunk/libs/thread/doc/thread.qbk (original)
+++ trunk/libs/thread/doc/thread.qbk 2013-03-10 10:54:59 EDT (Sun, 10 Mar 2013)
@@ -235,6 +235,7 @@
[include sync_tutorial.qbk]
[include mutex_concepts.qbk]
[include mutexes.qbk]
+[/include synchronized_value_ref.qbk]
[include condition_variables.qbk]
[include once.qbk]
[include barrier.qbk]
Modified: trunk/libs/thread/example/synchronized_person.cpp
==============================================================================
--- trunk/libs/thread/example/synchronized_person.cpp (original)
+++ trunk/libs/thread/example/synchronized_person.cpp 2013-03-10 10:54:59 EDT (Sun, 10 Mar 2013)
@@ -256,7 +256,7 @@
lk3->SetName("Matias");
}
#if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS \
-&& ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
+&& ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
{
Person3_ts p1(1);
Person3_ts p2(2);
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk