2 / Copyright (c) 2013 Vicente J. Botet Escriba
4 / Distributed under the Boost Software License, Version 1.0. (See accompanying
5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 [section:synchronized_value_ref Reference ]
11 #include <boost/thread/synchronized_value.hpp>
15 template<typename T, typename Lockable = mutex>
16 class synchronized_value;
18 // Specialized swap algorithm
19 template <typename T, typename L>
20 void swap(synchronized_value<T,L> & lhs, synchronized_value<T,L> & rhs);
21 template <typename T, typename L>
22 void swap(synchronized_value<T,L> & lhs, T & rhs);
23 template <typename T, typename L>
24 void swap(T & lhs, synchronized_value<T,L> & rhs);
27 template<typename T, typename L>
28 struct hash<synchronized_value<T,L> >;
31 template <typename T, typename L>
32 bool operator==(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
33 template <typename T, typename L>
34 bool operator!=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
35 template <typename T, typename L>
36 bool operator<(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
37 template <typename T, typename L>
38 bool operator<=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
39 template <typename T, typename L>
40 bool operator>(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
41 template <typename T, typename L>
42 bool operator>=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
45 template <typename T, typename L>
46 bool operator==(T const& lhs, synchronized_value<T,L> const&rhs);
47 template <typename T, typename L>
48 bool operator!=(T const& lhs, synchronized_value<T,L> const&rhs);
49 template <typename T, typename L>
50 bool operator<(T const& lhs, synchronized_value<T,L> const&rhs);
51 template <typename T, typename L>
52 bool operator<=(T const& lhs, synchronized_value<T,L> const&rhs);
53 template <typename T, typename L>
54 bool operator>(T const& lhs, synchronized_value<T,L> const&rhs);
55 template <typename T, typename L>
56 bool operator>=(T const& lhs, synchronized_value<T,L> const&rhs);
58 template <typename T, typename L>
59 bool operator==(synchronized_value<T,L> const& lhs, T const& rhs);
60 template <typename T, typename L>
61 bool operator!=(synchronized_value<T,L> const& lhs, T const& rhs);
62 template <typename T, typename L>
63 bool operator<(synchronized_value<T,L> const& lhs, T const& rhs);
64 template <typename T, typename L>
65 bool operator<=(synchronized_value<T,L> const& lhs, T const& rhs);
66 template <typename T, typename L>
67 bool operator>(synchronized_value<T,L> const& lhs, T const& rhs);
68 template <typename T, typename L>
69 bool operator>=(synchronized_value<T,L> const& lhs, T const& rhs);
71 #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
72 template <typename ...SV>
73 std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv);
77 [section:synchronized_value Class `synchronized_value`]
79 #include <boost/thread/synchronized_value.hpp>
84 template<typename T, typename Lockable = mutex>
85 class synchronized_value
89 typedef Lockable mutex_type;
91 synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
92 synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
93 synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
94 synchronized_value(synchronized_value const& rhs);
95 synchronized_value(synchronized_value&& other);
98 synchronized_value& operator=(synchronized_value const& rhs);
99 synchronized_value& operator=(value_type const& val);
100 void swap(synchronized_value & rhs);
101 void swap(value_type & rhs);
105 #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
106 explicit operator T() const;
109 strict_lock_ptr<T,Lockable> operator->();
110 const_strict_lock_ptr<T,Lockable> operator->() const;
111 strict_lock_ptr<T,Lockable> synchronize();
112 const_strict_lock_ptr<T,Lockable> synchronize() const;
114 deref_value operator*();;
115 const_deref_value operator*() const;
118 T value_; // for exposition only
119 mutable mutex_type mtx_; // for exposition only
125 [[Requires:] [`Lockable` is `Lockable`.]]
130 [section:constructor `synchronized_value()`]
132 synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
136 [[Requires:] [`T` is `DefaultConstructible`.]]
137 [[Effects:] [Default constructs the cloaked value_type]]
139 [[Throws:] [Any exception thrown by `value_type()`.]]
146 [section:constructor_vt `synchronized_value(T const&)`]
148 synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
152 [[Requires:] [`T` is `CopyConstructible`.]]
153 [[Effects:] [Copy constructs the cloaked value_type using the parameter `other`]]
155 [[Throws:] [Any exception thrown by `value_type(other)`.]]
161 [section:copy_cons `synchronized_value(synchronized_value const&)`]
163 synchronized_value(synchronized_value const& rhs);
167 [[Requires:] [`T` is `DefaultConstructible` and `Assignable`.]]
168 [[Effects:] [Assigns the value on a scope protected by the mutex of the rhs. The mutex is not copied.]]
170 [[Throws:] [Any exception thrown by `value_type()` or `value_type& operator=(value_type&)` or `mtx_.lock()`.]]
176 [section:move_vt `synchronized_value(T&&)`]
178 synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
182 [[Requires:] [`T` is `MoveConstructible `.]]
183 [[Effects:] [Move constructs the cloaked value_type]]
185 [[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
191 [section:move `synchronized_value(synchronized_value&&)`]
193 synchronized_value(synchronized_value&& other);
197 [[Requires:] [`T` is `MoveConstructible `.]]
198 [[Effects:] [Move constructs the cloaked value_type]]
200 [[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
206 [section:assign `operator=(synchronized_value const&)`]
208 synchronized_value& operator=(synchronized_value const& rhs);
212 [[Requires:] [`T` is `Assignable`.]]
213 [[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`.]]
214 [[Return:] [`*this`]]
216 [[Throws:] [Any exception thrown by `value_type& operator(value_type const&)` or `mtx_.lock()`.]]
221 [section:assign_vt `operator=(T const&)`]
223 synchronized_value& operator=(value_type const& val);
227 [[Requires:] [`T` is `Assignable`.]]
228 [[Effects:] [Copies the value on a scope protected by the mutex.]]
229 [[Return:] [`*this`]]
231 [[Throws:] [Any exception thrown by `value_type& operator(value_type const&)` or `mtx_.lock()`.]]
237 [section:get `get() const`]
243 [[Requires:] [`T` is `CopyConstructible`.]]
244 [[Return:] [`A copy of the protected value obtained on a scope protected by the mutex.`]]
246 [[Throws:] [Any exception thrown by `value_type(value_type const&)` or `mtx_.lock()`.]]
253 [section:T `operator T() const`]
255 #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
256 explicit operator T() const;
261 [[Requires:] [`T` is `CopyConstructible`.]]
262 [[Return:] [`A copy of the protected value obtained on a scope protected by the mutex.`]]
264 [[Throws:] [Any exception thrown by `value_type(value_type const&)` or `mtx_.lock()`.]]
270 [section:swap `swap(synchronized_value&)`]
272 void swap(synchronized_value & rhs);
276 [[Requires:] [`T` is `Assignable`.]]
277 [[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
279 [[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]
285 [section:swap_vt `swap(synchronized_value&)`]
287 void swap(value_type & rhs);
291 [[Requires:] [`T` is `Swapable`.]]
292 [[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
294 [[Throws:] [Any exception thrown by `swap(value_, rhs)` or `mtx_.lock()`.]]
299 [section:indir `operator->()`]
301 strict_lock_ptr<T,Lockable> operator->();
304 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.
308 [[Return:] [`A strict_lock_ptr<>.`]]
310 [[Throws:] [Nothing.]]
315 [section:indir_const `operator->() const`]
317 const_strict_lock_ptr<T,Lockable> operator->() const;
320 If the `synchronized_value` object involved is const-qualified, then you'll only be able to call const methods
321 through `operator->`. So, for example, `vec->push_back("xyz")` won't work if `vec` were const-qualified.
322 The locking mechanism capitalizes on the assumption that const methods don't modify their underlying data.
326 [[Return:] [`A const_strict_lock_ptr <>.`]]
328 [[Throws:] [Nothing.]]
333 [section:synchronize `synchronize()`]
335 strict_lock_ptr<T,Lockable> synchronize();
337 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.
341 void fun(synchronized_value<vector<int>> & vec) {
342 auto vec2=vec.synchronize();
344 assert(vec2.back() == 42);
349 [[Return:] [`A strict_lock_ptr <>.`]]
351 [[Throws:] [Nothing.]]
356 [section:synchronize_const `synchronize() const`]
358 const_strict_lock_ptr<T,Lockable> synchronize() const;
362 [[Return:] [`A const_strict_lock_ptr <>.`]]
364 [[Throws:] [Nothing.]]
370 [section:deref `operator*()`]
372 deref_value operator*();;
376 [[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.`]]
378 [[Throws:] [Nothing.]]
383 [section:deref_const `operator*() const`]
385 const_deref_value operator*() const;
390 [[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.`]]
392 [[Throws:] [Nothing.]]
402 [section:synchronize Non-Member Function `synchronize`]
404 #include <boost/thread/synchronized_value.hpp>
407 #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
408 template <typename ...SV>
409 std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv);