|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r83654 - trunk/libs/thread/doc
From: vicente.botet_at_[hidden]
Date: 2013-03-30 14:39:36
Author: viboes
Date: 2013-03-30 14:39:35 EDT (Sat, 30 Mar 2013)
New Revision: 83654
URL: http://svn.boost.org/trac/boost/changeset/83654
Log:
Thread: doc updated with sync queues draft and sections reorganization.
Added:
trunk/libs/thread/doc/sync_queues_ref.qbk (contents, props changed)
trunk/libs/thread/doc/sync_streams.qbk (contents, props changed)
trunk/libs/thread/doc/synchronized_value_ref.qbk (contents, props changed)
Text files modified:
trunk/libs/thread/doc/changes.qbk | 25 +
trunk/libs/thread/doc/mutexes.qbk | 404 ----------------------------------------
trunk/libs/thread/doc/sync_tutorial.qbk | 2
trunk/libs/thread/doc/synchronized_value.qbk | 13
trunk/libs/thread/doc/thread.qbk | 10
5 files changed, 38 insertions(+), 416 deletions(-)
Modified: trunk/libs/thread/doc/changes.qbk
==============================================================================
--- trunk/libs/thread/doc/changes.qbk (original)
+++ trunk/libs/thread/doc/changes.qbk 2013-03-30 14:39:35 EDT (Sat, 30 Mar 2013)
@@ -8,27 +8,42 @@
[section:changes History]
+[/
+[heading Version 4.2.0 - boost 1.55]
+
+[*New Features:]
+
+* [@http://svn.boost.org/trac/boost/ticket/8273 #8273] Add externally locked streams
+* [@http://svn.boost.org/trac/boost/ticket/8274 #8274] Add concurrent queue
+
+[*Fixed Bugs:]
+
+]
+
[heading Version 4.1.0 - boost 1.54]
+[*New Features:]
+
* [@http://svn.boost.org/trac/boost/ticket/7285 #7285] C++11 compliance: Allow to pass movable arguments for call_once.
* [@http://svn.boost.org/trac/boost/ticket/7449 #7449] Synchro: Add a synchronized value class
-[heading Version 4.0.0 - boost 1.53]
+[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/4882 #4882] Win32 shared_mutex does not handle timeouts correctly.
* [@http://svn.boost.org/trac/boost/ticket/6652 #6652] Boost.Thread shared_mutex.hpp:50:99: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
* [@http://svn.boost.org/trac/boost/ticket/7720 #7720] exception lock_error while intensive locking/unlocking of mutex
* [@http://svn.boost.org/trac/boost/ticket/7755 #7755] Thread: deadlock with shared_mutex on Windows
-* [@http://svn.boost.org/trac/boost/ticket/4882 #8070] prefer GetTickCount64 over GetTickCount
+* [@http://svn.boost.org/trac/boost/ticket/8027 #8027] thread library fails to compile with Visual Studio 2003
+* [@http://svn.boost.org/trac/boost/ticket/8070 #8070] prefer GetTickCount64 over GetTickCount
* [@http://svn.boost.org/trac/boost/ticket/8136 #8136] boost::this_thread::sleep_for() sleeps longer than it should in Windows
* [@http://svn.boost.org/trac/boost/ticket/8212 #8212] Boost thread compilation error on Solaris 10
* [@http://svn.boost.org/trac/boost/ticket/8237 #8237] fix documentation for 'thread_group'
* [@http://svn.boost.org/trac/boost/ticket/8239 #8239] barrier::wait() not marked as interruption_point
+* [@http://svn.boost.org/trac/boost/ticket/8323 #8323] boost::thread::try_join_for/try_join_until may block indefinitely due to a combination of problems in Boost.Thread and Boost.Chrono
+* [@http://svn.boost.org/trac/boost/ticket/8337 #8337] The internal representation of "std::string(this->code()->message())" escapes, but is destroyed when it exits scope.
-[*New Features:]
-
-[*Fixed Bugs:]
+[heading Version 4.0.0 - boost 1.53]
[/
[*Breaking changes:]
Modified: trunk/libs/thread/doc/mutexes.qbk
==============================================================================
--- trunk/libs/thread/doc/mutexes.qbk (original)
+++ trunk/libs/thread/doc/mutexes.qbk 2013-03-30 14:39:35 EDT (Sat, 30 Mar 2013)
@@ -240,409 +240,5 @@
[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]
Added: trunk/libs/thread/doc/sync_queues_ref.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/thread/doc/sync_queues_ref.qbk 2013-03-30 14:39:35 EDT (Sat, 30 Mar 2013)
@@ -0,0 +1,414 @@
+[section:synchronized_queues Synchronized Queues -- EXPERIMENTAL]
+
+[warning These features are experimental and subject to change in future versions. There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
+
+[note These features are based on the [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3533.html [*N3533 - C++ Concurrent Queues]] C++1y proposal from Lawrence Crowl and Chris Mysen and [@http://www.manning.com/williams/ [*C++ Concurrency in Action]] from Anthony Williams.]
+
+
+[section:tutorial Tutorial]
+
+Concurrent queues are a well know mechanism for communicating data between different threads.
+
+Concurrent queues have inherently copy/move semantics for the data handling operation. Reference-returning interfaces are forbidden as multiple access to these references can not be thread-safe.
+
+[endsect]
+
+[section:ref Reference]
+
+[section:sync_queue_req Synchronized Queue Model]
+
+The BasicConcurrentQueue concept models .
+A type `Q` meets the BasicConcurrentQueue requirements if the following expressions are well-formed and have the specified semantics
+
+* `q` denotes a value of type `Q`,
+* `e` denotes a value of type Q::value_type,
+* `u` denotes a value of type Q::size_type,
+* `lve` denotes a lvalue referece of type Q::value_type,
+* `rve` denotes a rvalue referece of type Q::value_type:
+* `spe` denotes a shared_ptr<Q::value_type>
+
+Basic expressions
+
+* Q::value_type
+* Q::size_type
+* `q.push(e);`
+* `q.push(rve);`
+* `q.pull(lre);`
+* `lre = q.pull();`
+* `spe = q.ptr_pull();`
+* `b = q.empty();`
+* `u = q.size();`
+
+Non-waiting operations
+
+* `b = q.try_push(e);`
+* `b = q.try_push(rve);`
+* `b = q.try_pull(lre);`
+
+Non-blocking operations are provided by BlockingQueues
+
+* `b = q.try_push(nb, e);`
+* `b = q.try_push(nb, rve);`
+* `b = q.try_pull(nb, lre);`
+
+Bounded queues add the following valid expressions
+
+* `Q q(u);`
+* `b = q.full();`
+* `u = q.capacity();`
+
+Closed queues
+
+Threads using a queue for communication need some mechanism to signal when the queue is no longer needed. The usual approach is add an additional out-of-band signal. However, this approach suffers from the flaw that threads waiting on either full or empty queues need to be woken up when the queue is no longer needed. Rather than require an out-of-band signal, we chose to directly support such a signal in the queue itself, which considerably simplifies coding.
+
+To achieve this signal, a thread may close a queue. Once closed, no new elements may be pushed onto the queue. Push operations on a closed queue will either return queue_op_status::closed (when they have a queue_op_status return type), set the closed parameter if it has one or throw sync_queue::closed (when they do not). Elements already on the queue may be popped off. When a queue is empty and closed, pop operations will either return queue_op_status::closed (when they have a status return) or throw queue_op_status::closed (when they do not).
+
+* `q.close();`
+* `b = q.closed();`
+
+Basic expressions
+
+* Q::value_type
+* `q.push(e,c);`
+* `q.push(rve,c);`
+* `q.pull(lre,c);`
+* `spe = q.ptr_pull(c);`
+
+Non-waiting operations
+
+* `b = q.try_push(e, c);`
+* `b = q.try_push(rve, c);`
+* `b = q.try_pull(lre, c);`
+
+Non-blocking operations are provided by BlockingQueues
+
+* `b = q.try_push(nb, e, c);`
+* `b = q.try_push(nb, rve, c);`
+* `b = q.try_pull(nb, lre, c);`
+
+
+[section:exception Blocking Queues Throw specification]
+
+All the functions that can throw are defined as if we had in addition to its specific Throw specification the following:
+
+[variablelist
+[[Throws:] [Any exception thrown by the internal locking.]]
+]
+
+[endsect]
+
+
+[section:exception2 Closed Queues Throw specification]
+
+All the modifier functions that have no a specific closed parameter can throw are defined as if we had in addition to its specific Throw specification the following:
+
+[variablelist
+[[Throws:] [Any exception thrown by the internal locking.]]
+]
+
+[endsect]
+
+
+[section:push `q.push(e);`]
+
+[variablelist
+
+[[Effects:] [Waits until the queue is not full (for bounded queues) and then push the `e` onto the queue copying it.]]
+
+[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
+
+[[Postcondition:] [`! q.empty()`.]]
+
+[[Return type:] [`void`.]]
+
+[[Throws:] [If the queue was closed, throws sync_queue_is_closed. Any exception thrown by the the copy of `e`.]]
+
+[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
+
+]
+
+[endsect]
+[section:push_m `q.push(rve);`]
+
+[variablelist
+
+[[Effects:] [Waits until the queue is not full (for bounded queues) and then push the `e` onto the queue moving it.]]
+
+[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
+
+[[Postcondition:] [`! q.empty()`.]]
+
+[[Return type:] [`void`.]]
+
+[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the the copy of `e`.]]
+
+[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
+
+]
+
+[endsect]
+
+[section:try_push `q.try_push(e);`]
+
+[variablelist
+
+[[Effects:] [If the queue `q` is not full, push the `e` onto the queue copying it.]]
+
+[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation when the operation succeeds. ]]
+
+[[Return type:] [`bool`.]]
+
+[[Return:] [If the queue `q` is full return `false`, otherwise return `true`;]]
+
+[[Postcondition:] [If the call returns `true`, `! q.empty()`.]]
+
+[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the the copy of `e`.]]
+
+[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
+
+]
+
+[endsect]
+[section:try_push_m `q.try_push(rve());`]
+
+[variablelist
+
+[[Effects:] [If the queue `q` is not full, push the `e` onto the queue moving it.]]
+
+[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
+
+[[Return type:] [`bool`.]]
+
+[[Return:] [If the queue `q` is full return `false`, otherwise return `true`;]]
+
+[[Postcondition:] [If the call returns `true`, `! q.empty()`.]]
+
+[[Throws:] [If the queue is closed, throws sync_queue_is_closed. Any exception thrown by the the copy of `e`.]]
+
+[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
+
+]
+
+[endsect]
+[section:pull `e = q.pull()`]
+
+[variablelist
+
+[[Requires:] [Q::value_type is no throw copy movable. This is needed to ensure the exception safety]]
+
+[[Effects:] [Waits until the queue is not empty and then pull the element from the queue `q` and moves the pulled element.]]
+
+[[Synchronization:] [Prior pull-like operations on the same object synchronizes with this operation.]]
+
+[[Postcondition:] [`! q.full()`.]]
+
+[[Return type:] [`Q::value_type`.]]
+
+[[Return:] [The pulled element.]]
+
+[[Throws:] [Any exception thrown by the copy of `e`.]]
+
+[[Exception safety:] [If an exception is thrown then the queue state is unmodified.]]
+
+]
+
+[endsect]
+
+
+[endsect]
+
+[section:sync_bounded_queue_ref Synchronized Bounded Queue]
+
+ #include <boost/thread/sync_bounded_queue.hpp>
+
+ namespace boost
+ {
+ struct sync_queue_is_closed : std::exception {};
+
+ template <typename ValueType>
+ class sync_bounded_queue;
+
+ // Stream-like operators
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, ValueType&& elem);
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, ValueType const&elem);
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator>>(sync_bounded_queue<ValueType>& sbq, ValueType &elem);
+ }
+
+[section:sync_queue_is_closed Class `sync_queue_is_closed`]
+
+ #include <boost/thread/sync_bounded_queue.hpp>
+
+ namespace boost
+ {
+ struct sync_queue_is_closed : std::exception {};
+ }
+
+[endsect]
+
+[section:sync_bounded_queue Class `sync_bounded_queue<>`]
+
+ #include <boost/thread/sync_bounded_queue.hpp>
+ namespace boost
+ {
+ template <typename ValueType>
+ class sync_bounded_queue
+ {
+ public:
+ typedef ValueType value_type;
+ typedef std::size_t size_type;
+
+ sync_bounded_queue(sync_bounded_queue const&) = delete;
+ sync_bounded_queue& operator=(sync_bounded_queue const&) = delete;
+ explicit sync_bounded_queue(size_type max_elems);
+ template <typename Range>
+ sync_bounded_queue(size_type max_elems, Range range);
+ ~sync_bounded_queue();
+
+ // Observers
+ bool empty() const;
+ bool full() const;
+ size_type capacity() const;
+ size_type size() const;
+ bool closed() const;
+
+ // Modifiers
+ void push(const value_type& x);
+ void push(value_type&& x);
+ bool try_push(const value_type& x);
+ bool try_push(value_type&& x);
+ bool try_push(no_block_tag, const value_type& x);
+ bool try_push(no_block_tag, value_type&& x);
+
+ void pull(value_type&);
+ // enable_if is_nothrow_movable<value_type>
+ value_type pull();
+ shared_ptr<ValueType> ptr_pull();
+ bool try_pull(value_type&);
+ bool try_pull(no_block_tag,value_type&);
+ shared_ptr<ValueType> try_pull();
+
+ void close();
+ };
+ }
+
+[endsect]
+
+[section:stream_out_operators Non-Member Function `operator<<()`]
+
+ #include <boost/thread/sync_bounded_queue.hpp>
+ namespace boost
+ {
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, ValueType&& elem);
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, ValueType const&elem);
+ }
+
+[endsect]
+[section:stream_in_operators Non-Member Function `operator>>()`]
+
+ #include <boost/thread/sync_bounded_queue.hpp>
+ namespace boost
+ {
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator>>(sync_bounded_queue<ValueType>& sbq, ValueType &elem);
+ }
+
+[endsect]
+[endsect]
+
+[section:sync_queue_ref Synchronized Unbounded Queue]
+
+ #include <boost/thread/sync_queue.hpp>
+ namespace boost
+ {
+ template <typename ValueType>
+ class sync_queue;
+
+ // Stream-like operators
+ template <typename ValueType>
+ sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType&& elem);
+ template <typename ValueType>
+ sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem);
+ template <typename ValueType>
+ sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem);
+ }
+
+[section:sync_queue Class `sync_queue<>`]
+
+ #include <boost/thread/sync_queue.hpp>
+
+ namespace boost
+ {
+ template <typename ValueType>
+ class sync_queue
+ {
+ public:
+ typedef ValueType value_type;
+ typedef std::size_t size_type;
+
+ sync_queue(sync_queue const&) = delete;
+ sync_queue& operator=(sync_queue const&) = delete;
+ sync_queue();
+ explicit template <typename Range>
+ sync_queue(Range range);
+ ~sync_queue();
+
+ // Observers
+ bool empty() const;
+ bool full() const;
+ size_type size() const;
+ bool closed() const;
+
+ // Modifiers
+ void push(const value_type& x);
+ void push(value_type&& x);
+ bool try_push(const value_type& x);
+ bool try_push(value_type&&) x);
+ bool try_push(no_block_tag, const value_type& x);
+ bool try_push(no_block_tag, value_type&& x);
+
+ void pull(value_type&);
+ // enable_if is_nothrow_movable<value_type>
+ value_type pull();
+ shared_ptr<ValueType> ptr_pull();
+ bool try_pull(value_type&);
+ bool try_pull(no_block_tag,value_type&);
+ shared_ptr<ValueType> try_pull();
+
+ void close();
+ };
+ }
+
+[endsect]
+
+[section:stream_out_operators Non-Member Function `operator<<()`]
+
+ #include <boost/thread/sync_queue.hpp>
+ namespace boost
+ {
+ template <typename ValueType>
+ sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType&& elem);
+ template <typename ValueType>
+ sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem);
+ }
+
+[endsect]
+[section:stream_in_operators Non-Member Function `operator>>()`]
+
+ #include <boost/thread/sync_queue.hpp>
+ namespace boost
+ {
+ template <typename ValueType>
+ sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem);
+ }
+
+[endsect]
+
+[endsect]
+
+[endsect]
+[endsect]
Added: trunk/libs/thread/doc/sync_streams.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/thread/doc/sync_streams.qbk 2013-03-30 14:39:35 EDT (Sat, 30 Mar 2013)
@@ -0,0 +1,109 @@
+[/
+ / Copyright (c) 2013 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:ext_locked_streams Externally Locked Streams - EXPERIMENTAL]
+
+[warning These features are experimental and subject to change in future versions. There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
+
+[note These features are based on the [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3535.html [*N3535 - C++ Streams Mutex]] C++1y proposal, even if the library proposes al alternative interface.]
+
+[section:tutorial Tutorial]
+
+[endsect] [/tutorial]
+
+[section:ref Reference]
+
+ #include <boost/thread/externally_locked_stream.hpp>
+ namespace boost
+ {
+ template <typename Stream, typename RecursiveMutex=recursive_mutex>
+ class externally_locked_stream;
+ template <class Stream, typename RecursiveMutex=recursive_mutex>
+ class stream_guard;
+ template <typename Stream, typename RecursiveMutex>
+ struct is_strict_lock_sur_parolle<stream_guard<Stream, RecursiveMutex> > : true_type {};
+
+ // Stream-like operators
+ template <typename Stream, typename RecursiveMutex, typename T>
+ const stream_guard<Stream, RecursiveMutex>& operator<<(const stream_guard<Stream, RecursiveMutex>& lck, T arg);
+ template <typename Stream, typename RecursiveMutex>
+ const stream_guard<Stream, RecursiveMutex>&
+ operator<<(const stream_guard<Stream, RecursiveMutex>& lck, Stream& (*arg)(Stream&));
+ template <typename Stream, typename RecursiveMutex, typename T>
+ const stream_guard<Stream, RecursiveMutex>&
+ operator>>(const stream_guard<Stream, RecursiveMutex>& lck, T& arg);
+ template <typename Stream, typename RecursiveMutex, typename T>
+ stream_guard<Stream, RecursiveMutex>
+ operator<<(externally_locked_stream<Stream, RecursiveMutex>& mtx, T arg);
+ template <typename Stream, typename RecursiveMutex>
+ stream_guard<Stream, RecursiveMutex>
+ operator<<(externally_locked_stream<Stream, RecursiveMutex>& mtx, Stream& (*arg)(Stream&));
+ template <typename Stream, typename RecursiveMutex, typename T>
+ stream_guard<Stream, RecursiveMutex>
+ operator>>(externally_locked_stream<Stream, RecursiveMutex>& mtx, T& arg);
+ }
+
+
+[section:stream_guard Class `stream_guard`]
+
+ #include <boost/thread/externally_locked_stream.hpp>
+ namespace boost
+ {
+ template <class Stream, typename RecursiveMutex=recursive_mutex>
+ class stream_guard
+ {
+ public:
+ typedef typename externally_locked_stream<Stream, RecursiveMutex>::mutex_type mutex_type;
+
+ // Constructors, Assignment and Destructors
+ stream_guard(stream_guard const&) = delete;
+ stream_guard& operator=(stream_guard const&) = delete;
+ stream_guard(externally_locked_stream<Stream, RecursiveMutex>& mtx);
+ stream_guard(externally_locked_stream<Stream, RecursiveMutex>& mtx, adopt_lock_t);
+ stream_guard(BOOST_THREAD_RV_REF(stream_guard) rhs);
+ ~stream_guard();
+
+ // Observers
+ bool owns_lock(mutex_type const* l) const BOOST_NOEXCEPT;
+ Stream& get() const;
+ };
+ }
+
+[endsect]
+[section:externally_locked_stream Class `externally_locked_stream `]
+
+ #include <boost/thread/externally_locked_stream.hpp>
+ namespace boost
+ {
+ template <typename Stream, typename RecursiveMutex>
+ class externally_locked_stream: public externally_locked<Stream&, RecursiveMutex>
+ {
+ public:
+ // Constructors, Assignment and Destructors
+ externally_locked_stream(externally_locked_stream const&) = delete;
+ externally_locked_stream& operator=(externally_locked_stream const&) = delete;
+ // Effects: Constructs an externally locked object storing the cloaked reference object.
+ externally_locked_stream(Stream& stream, RecursiveMutex& mtx);
+
+ // Observers
+ stream_guard<Stream, RecursiveMutex> hold();
+ Stream& hold(strict_lock<RecursiveMutex>& lk);
+ };
+ }
+
+`externally_locked_stream` cloaks a reference to an stream of type `Stream`, and actually
+provides full access to that object through the `get` member functions, provided you
+pass a reference to a strict lock object.
+
+
+[endsect]
+
+
+[endsect] [/ref]
+
+[endsect] [/Externally Locked Streams]
Modified: trunk/libs/thread/doc/sync_tutorial.qbk
==============================================================================
--- trunk/libs/thread/doc/sync_tutorial.qbk (original)
+++ trunk/libs/thread/doc/sync_tutorial.qbk 2013-03-30 14:39:35 EDT (Sat, 30 Mar 2013)
@@ -18,8 +18,6 @@
[include external_locking.qbk]
-[include synchronized_value.qbk]
-
[section:with Executing Around a Function]
In particular, the library provides some lock factories.
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-30 14:39:35 EDT (Sat, 30 Mar 2013)
@@ -6,7 +6,13 @@
/]
-[section Synchronized values]
+[section:synchronized_valuesxxx Synchronized values - EXPERIMENTAL]
+
+[warning These features are experimental and subject to change in future versions. There are not too much tests yet, so it is possible that you can find out some trivial bugs :(]
+
+[section:tutorial Tutorial]
+
+
[note This tutorial is an adaptation of the paper of Anthony Williams "Enforcing Correct Mutex Usage with Synchronized Values" to the Boost library.]
[section The Problem with Mutexes]
@@ -133,8 +139,9 @@
[endsect] [/Value semantics]
-[endsect] [/Synchronized variables]
-
+[endsect] [/tutorial]
+[include synchronized_value_ref.qbk]
+[endsect] [/Synchronized values]
Added: trunk/libs/thread/doc/synchronized_value_ref.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/thread/doc/synchronized_value_ref.qbk 2013-03-30 14:39:35 EDT (Sat, 30 Mar 2013)
@@ -0,0 +1,408 @@
+[section:synchronized_value_ref Reference ]
+
+
+ #include <boost/thread/synchronized_value.hpp>
+ 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/thread.qbk
==============================================================================
--- trunk/libs/thread/doc/thread.qbk (original)
+++ trunk/libs/thread/doc/thread.qbk 2013-03-30 14:39:35 EDT (Sat, 30 Mar 2013)
@@ -8,7 +8,7 @@
[library Thread
[quickbook 1.5]
- [version 4.0.0]
+ [version 4.1.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-12 Vicente J. Botet Escriba]
@@ -235,15 +235,21 @@
[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]
[include futures.qbk]
[endsect]
+
[include tss.qbk]
+[section:sds Synchronized Data Structures]
+[include synchronized_value.qbk]
+[/include sync_queues_ref.qbk]
+[/include sync_streams.qbk]
+[endsect]
+
[include time.qbk]
[include emulations.qbk]
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