synchronized_value_ref.qbk 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. [/
  2. / Copyright (c) 2013 Vicente J. Botet Escriba
  3. /
  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)
  6. /]
  7. [section:synchronized_value_ref Reference ]
  8. #include <boost/thread/synchronized_value.hpp>
  9. namespace boost
  10. {
  11. template<typename T, typename Lockable = mutex>
  12. class synchronized_value;
  13. // Specialized swap algorithm
  14. template <typename T, typename L>
  15. void swap(synchronized_value<T,L> & lhs, synchronized_value<T,L> & rhs);
  16. template <typename T, typename L>
  17. void swap(synchronized_value<T,L> & lhs, T & rhs);
  18. template <typename T, typename L>
  19. void swap(T & lhs, synchronized_value<T,L> & rhs);
  20. // Hash support
  21. template<typename T, typename L>
  22. struct hash<synchronized_value<T,L> >;
  23. // Comparison
  24. template <typename T, typename L>
  25. bool operator==(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
  26. template <typename T, typename L>
  27. bool operator!=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
  28. template <typename T, typename L>
  29. bool operator<(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
  30. template <typename T, typename L>
  31. bool operator<=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
  32. template <typename T, typename L>
  33. bool operator>(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
  34. template <typename T, typename L>
  35. bool operator>=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
  36. // Comparison with T
  37. template <typename T, typename L>
  38. bool operator==(T const& lhs, synchronized_value<T,L> const&rhs);
  39. template <typename T, typename L>
  40. bool operator!=(T const& lhs, synchronized_value<T,L> const&rhs);
  41. template <typename T, typename L>
  42. bool operator<(T const& lhs, synchronized_value<T,L> const&rhs);
  43. template <typename T, typename L>
  44. bool operator<=(T 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==(synchronized_value<T,L> const& lhs, T const& rhs);
  51. template <typename T, typename L>
  52. bool operator!=(synchronized_value<T,L> const& lhs, T const& rhs);
  53. template <typename T, typename L>
  54. bool operator<(synchronized_value<T,L> const& lhs, T const& rhs);
  55. template <typename T, typename L>
  56. bool operator<=(synchronized_value<T,L> const& lhs, T const& rhs);
  57. template <typename T, typename L>
  58. bool operator>(synchronized_value<T,L> const& lhs, T const& rhs);
  59. template <typename T, typename L>
  60. bool operator>=(synchronized_value<T,L> const& lhs, T const& rhs);
  61. #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
  62. template <typename ...SV>
  63. std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv);
  64. #endif
  65. }
  66. [section:synchronized_value Class `synchronized_value`]
  67. #include <boost/thread/synchronized_value.hpp>
  68. namespace boost
  69. {
  70. template<typename T, typename Lockable = mutex>
  71. class synchronized_value
  72. {
  73. public:
  74. typedef T value_type;
  75. typedef Lockable mutex_type;
  76. synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
  77. synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
  78. synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
  79. synchronized_value(synchronized_value const& rhs);
  80. synchronized_value(synchronized_value&& other);
  81. // mutation
  82. synchronized_value& operator=(synchronized_value const& rhs);
  83. synchronized_value& operator=(value_type const& val);
  84. void swap(synchronized_value & rhs);
  85. void swap(value_type & rhs);
  86. //observers
  87. T get() const;
  88. #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
  89. explicit operator T() const;
  90. #endif
  91. strict_lock_ptr<T,Lockable> operator->();
  92. const_strict_lock_ptr<T,Lockable> operator->() const;
  93. strict_lock_ptr<T,Lockable> synchronize();
  94. const_strict_lock_ptr<T,Lockable> synchronize() const;
  95. deref_value operator*();;
  96. const_deref_value operator*() const;
  97. private:
  98. T value_; // for exposition only
  99. mutable mutex_type mtx_; // for exposition only
  100. };
  101. }
  102. [variablelist
  103. [[Requires:] [`Lockable` is `Lockable`.]]
  104. ]
  105. [section:constructor `synchronized_value()`]
  106. synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
  107. [variablelist
  108. [[Requires:] [`T` is `DefaultConstructible`.]]
  109. [[Effects:] [Default constructs the cloaked value_type]]
  110. [[Throws:] [Any exception thrown by `value_type()`.]]
  111. ]
  112. [endsect]
  113. [section:constructor_vt `synchronized_value(T const&)`]
  114. synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
  115. [variablelist
  116. [[Requires:] [`T` is `CopyConstructible`.]]
  117. [[Effects:] [Copy constructs the cloaked value_type using the parameter `other`]]
  118. [[Throws:] [Any exception thrown by `value_type(other)`.]]
  119. ]
  120. [endsect]
  121. [section:copy_cons `synchronized_value(synchronized_value const&)`]
  122. synchronized_value(synchronized_value const& rhs);
  123. [variablelist
  124. [[Requires:] [`T` is `DefaultConstructible` and `Assignable`.]]
  125. [[Effects:] [Assigns the value on a scope protected by the mutex of the rhs. The mutex is not copied.]]
  126. [[Throws:] [Any exception thrown by `value_type()` or `value_type& operator=(value_type&)` or `mtx_.lock()`.]]
  127. ]
  128. [endsect]
  129. [section:move_vt `synchronized_value(T&&)`]
  130. synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
  131. [variablelist
  132. [[Requires:] [`T` is `MoveConstructible `.]]
  133. [[Effects:] [Move constructs the cloaked value_type]]
  134. [[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
  135. ]
  136. [endsect]
  137. [section:move `synchronized_value(synchronized_value&&)`]
  138. synchronized_value(synchronized_value&& other);
  139. [variablelist
  140. [[Requires:] [`T` is `MoveConstructible `.]]
  141. [[Effects:] [Move constructs the cloaked value_type]]
  142. [[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
  143. ]
  144. [endsect]
  145. [section:assign `operator=(synchronized_value const&)`]
  146. synchronized_value& operator=(synchronized_value const& rhs);
  147. [variablelist
  148. [[Requires:] [`T` is `Assignable`.]]
  149. [[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`.]]
  150. [[Return:] [`*this`]]
  151. [[Throws:] [Any exception thrown by `value_type& operator(value_type const&)` or `mtx_.lock()`.]]
  152. ]
  153. [endsect]
  154. [section:assign_vt `operator=(T const&)`]
  155. synchronized_value& operator=(value_type const& val);
  156. [variablelist
  157. [[Requires:] [`T` is `Assignable`.]]
  158. [[Effects:] [Copies the value on a scope protected by the mutex.]]
  159. [[Return:] [`*this`]]
  160. [[Throws:] [Any exception thrown by `value_type& operator(value_type const&)` or `mtx_.lock()`.]]
  161. ]
  162. [endsect]
  163. [section:get `get() const`]
  164. T get() const;
  165. [variablelist
  166. [[Requires:] [`T` is `CopyConstructible`.]]
  167. [[Return:] [`A copy of the protected value obtained on a scope protected by the mutex.`]]
  168. [[Throws:] [Any exception thrown by `value_type(value_type const&)` or `mtx_.lock()`.]]
  169. ]
  170. [endsect]
  171. [section:T `operator T() const`]
  172. #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
  173. explicit operator T() const;
  174. #endif
  175. [variablelist
  176. [[Requires:] [`T` is `CopyConstructible`.]]
  177. [[Return:] [`A copy of the protected value obtained on a scope protected by the mutex.`]]
  178. [[Throws:] [Any exception thrown by `value_type(value_type const&)` or `mtx_.lock()`.]]
  179. ]
  180. [endsect]
  181. [section:swap `swap(synchronized_value&)`]
  182. void swap(synchronized_value & rhs);
  183. [variablelist
  184. [[Requires:] [`T` is `Assignable`.]]
  185. [[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
  186. [[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]
  187. ]
  188. [endsect]
  189. [section:swap_vt `swap(synchronized_value&)`]
  190. void swap(value_type & rhs);
  191. [variablelist
  192. [[Requires:] [`T` is `Swapable`.]]
  193. [[Effects:] [Swaps the data on a scope protected by both mutex. Both mutex are acquired to avoid dead-lock. The mutexes are not swapped.]]
  194. [[Throws:] [Any exception thrown by `swap(value_, rhs)` or `mtx_.lock()`.]]
  195. ]
  196. [endsect]
  197. [section:indir `operator->()`]
  198. strict_lock_ptr<T,Lockable> operator->();
  199. 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.
  200. [variablelist
  201. [[Return:] [`A strict_lock_ptr<>.`]]
  202. [[Throws:] [Nothing.]]
  203. ]
  204. [endsect]
  205. [section:indir_const `operator->() const`]
  206. const_strict_lock_ptr<T,Lockable> operator->() const;
  207. If the `synchronized_value` object involved is const-qualified, then you'll only be able to call const methods
  208. through `operator->`. So, for example, `vec->push_back("xyz")` won't work if `vec` were const-qualified.
  209. The locking mechanism capitalizes on the assumption that const methods don't modify their underlying data.
  210. [variablelist
  211. [[Return:] [`A const_strict_lock_ptr <>.`]]
  212. [[Throws:] [Nothing.]]
  213. ]
  214. [endsect]
  215. [section:synchronize `synchronize()`]
  216. strict_lock_ptr<T,Lockable> synchronize();
  217. 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.
  218. [*Example:]
  219. void fun(synchronized_value<vector<int>> & vec) {
  220. auto vec2=vec.synchronize();
  221. vec2.push_back(42);
  222. assert(vec2.back() == 42);
  223. }
  224. [variablelist
  225. [[Return:] [`A strict_lock_ptr <>.`]]
  226. [[Throws:] [Nothing.]]
  227. ]
  228. [endsect]
  229. [section:synchronize_const `synchronize() const`]
  230. const_strict_lock_ptr<T,Lockable> synchronize() const;
  231. [variablelist
  232. [[Return:] [`A const_strict_lock_ptr <>.`]]
  233. [[Throws:] [Nothing.]]
  234. ]
  235. [endsect]
  236. [section:deref `operator*()`]
  237. deref_value operator*();;
  238. [variablelist
  239. [[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.`]]
  240. [[Throws:] [Nothing.]]
  241. ]
  242. [endsect]
  243. [section:deref_const `operator*() const`]
  244. const_deref_value operator*() const;
  245. [variablelist
  246. [[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.`]]
  247. [[Throws:] [Nothing.]]
  248. ]
  249. [endsect]
  250. [endsect]
  251. [section:synchronize Non-Member Function `synchronize`]
  252. #include <boost/thread/synchronized_value.hpp>
  253. namespace boost
  254. {
  255. #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
  256. template <typename ...SV>
  257. std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv);
  258. #endif
  259. }
  260. [endsect]
  261. [endsect]