• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
8[section:synchronized_value_ref Reference ]
9
10
11  #include <boost/thread/synchronized_value.hpp>
12  namespace boost
13  {
14
15    template<typename T, typename Lockable = mutex>
16    class synchronized_value;
17
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);
25
26    // Hash support
27    template<typename T, typename L>
28    struct hash<synchronized_value<T,L> >;
29
30    // Comparison
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)
43
44    // Comparison with T
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);
57
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);
70
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);
74  #endif
75  }
76
77[section:synchronized_value Class `synchronized_value`]
78
79  #include <boost/thread/synchronized_value.hpp>
80
81  namespace boost
82  {
83
84    template<typename T, typename Lockable = mutex>
85    class synchronized_value
86    {
87    public:
88      typedef T value_type;
89      typedef Lockable mutex_type;
90
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);
96
97      // mutation
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);
102
103      //observers
104      T get() const;
105    #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
106      explicit operator T() const;
107    #endif
108
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;
113
114      deref_value operator*();;
115      const_deref_value operator*() const;
116
117    private:
118      T value_; // for exposition only
119      mutable mutex_type mtx_;  // for exposition only
120    };
121  }
122
123[variablelist
124
125[[Requires:] [`Lockable` is `Lockable`.]]
126
127]
128
129
130[section:constructor `synchronized_value()`]
131
132      synchronized_value() noexcept(is_nothrow_default_constructible<T>::value);
133
134[variablelist
135
136[[Requires:] [`T` is `DefaultConstructible`.]]
137[[Effects:] [Default constructs the cloaked value_type]]
138
139[[Throws:] [Any exception thrown by `value_type()`.]]
140
141]
142
143[endsect]
144
145
146[section:constructor_vt `synchronized_value(T const&)`]
147
148      synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
149
150[variablelist
151
152[[Requires:] [`T` is `CopyConstructible`.]]
153[[Effects:] [Copy constructs the cloaked value_type using the parameter `other`]]
154
155[[Throws:] [Any exception thrown by `value_type(other)`.]]
156
157]
158
159[endsect]
160
161[section:copy_cons `synchronized_value(synchronized_value const&)`]
162
163      synchronized_value(synchronized_value const& rhs);
164
165[variablelist
166
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.]]
169
170[[Throws:] [Any exception thrown by `value_type()` or `value_type& operator=(value_type&)` or `mtx_.lock()`.]]
171
172]
173
174[endsect]
175
176[section:move_vt `synchronized_value(T&&)`]
177
178      synchronized_value(T&& other) noexcept(is_nothrow_move_constructible<T>::value);
179
180[variablelist
181
182[[Requires:] [`T` is `MoveConstructible `.]]
183[[Effects:] [Move constructs the cloaked value_type]]
184
185[[Throws:] [Any exception thrown by `value_type(value_type&&)`.]]
186
187]
188
189[endsect]
190
191[section:move `synchronized_value(synchronized_value&&)`]
192
193      synchronized_value(synchronized_value&& other);
194
195[variablelist
196
197[[Requires:] [`T` is `MoveConstructible `.]]
198[[Effects:] [Move constructs the cloaked value_type]]
199
200[[Throws:] [Any exception thrown by `value_type(value_type&&)` or `mtx_.lock()`.]]
201
202]
203
204[endsect]
205
206[section:assign `operator=(synchronized_value const&)`]
207
208      synchronized_value& operator=(synchronized_value const& rhs);
209
210[variablelist
211
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`]]
215
216[[Throws:] [Any exception thrown by `value_type& operator(value_type const&)` or `mtx_.lock()`.]]
217
218]
219
220[endsect]
221[section:assign_vt `operator=(T const&)`]
222
223      synchronized_value& operator=(value_type const& val);
224
225[variablelist
226
227[[Requires:] [`T` is `Assignable`.]]
228[[Effects:] [Copies the value on a scope protected by the mutex.]]
229[[Return:] [`*this`]]
230
231[[Throws:] [Any exception thrown by `value_type& operator(value_type const&)` or `mtx_.lock()`.]]
232
233]
234
235[endsect]
236
237[section:get `get() const`]
238
239      T get() const;
240
241[variablelist
242
243[[Requires:] [`T` is `CopyConstructible`.]]
244[[Return:] [`A copy of the protected value obtained on a scope protected by the mutex.`]]
245
246[[Throws:] [Any exception thrown by `value_type(value_type const&)` or `mtx_.lock()`.]]
247
248]
249
250[endsect]
251
252
253[section:T `operator T() const`]
254
255    #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
256      explicit operator T() const;
257    #endif
258
259[variablelist
260
261[[Requires:] [`T` is `CopyConstructible`.]]
262[[Return:] [`A copy of the protected value obtained on a scope protected by the mutex.`]]
263
264[[Throws:] [Any exception thrown by `value_type(value_type const&)` or `mtx_.lock()`.]]
265
266]
267
268[endsect]
269
270[section:swap `swap(synchronized_value&)`]
271
272      void swap(synchronized_value & rhs);
273
274[variablelist
275
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.]]
278
279[[Throws:] [Any exception thrown by `swap(value_, rhs.value)` or `mtx_.lock()` or `rhs_.mtx_.lock()`.]]
280
281]
282
283[endsect]
284
285[section:swap_vt `swap(synchronized_value&)`]
286
287      void swap(value_type & rhs);
288
289[variablelist
290
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.]]
293
294[[Throws:] [Any exception thrown by `swap(value_, rhs)` or `mtx_.lock()`.]]
295
296]
297
298[endsect]
299[section:indir `operator->()`]
300
301      strict_lock_ptr<T,Lockable> operator->();
302
303
304Essentially 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.
305
306[variablelist
307
308[[Return:] [`A strict_lock_ptr<>.`]]
309
310[[Throws:] [Nothing.]]
311
312]
313
314[endsect]
315[section:indir_const `operator->() const`]
316
317      const_strict_lock_ptr<T,Lockable> operator->() const;
318
319
320If the `synchronized_value` object involved is const-qualified, then you'll only be able to call const methods
321through `operator->`. So, for example, `vec->push_back("xyz")` won't work if `vec` were const-qualified.
322The locking mechanism capitalizes on the assumption that const methods don't modify their underlying data.
323
324[variablelist
325
326[[Return:] [`A const_strict_lock_ptr <>.`]]
327
328[[Throws:] [Nothing.]]
329
330]
331
332[endsect]
333[section:synchronize `synchronize()`]
334
335    strict_lock_ptr<T,Lockable> synchronize();
336
337The 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.
338
339[*Example:]
340
341  void fun(synchronized_value<vector<int>> & vec) {
342    auto vec2=vec.synchronize();
343    vec2.push_back(42);
344    assert(vec2.back() == 42);
345  }
346
347[variablelist
348
349[[Return:] [`A strict_lock_ptr <>.`]]
350
351[[Throws:] [Nothing.]]
352
353]
354
355[endsect]
356[section:synchronize_const `synchronize() const`]
357
358    const_strict_lock_ptr<T,Lockable> synchronize() const;
359
360[variablelist
361
362[[Return:] [`A const_strict_lock_ptr <>.`]]
363
364[[Throws:] [Nothing.]]
365
366]
367
368[endsect]
369
370[section:deref `operator*()`]
371
372      deref_value operator*();;
373
374[variablelist
375
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.`]]
377
378[[Throws:] [Nothing.]]
379
380]
381
382[endsect]
383[section:deref_const `operator*() const`]
384
385      const_deref_value operator*() const;
386
387
388[variablelist
389
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.`]]
391
392[[Throws:] [Nothing.]]
393
394]
395
396[endsect]
397
398
399
400
401[endsect]
402[section:synchronize Non-Member Function `synchronize`]
403
404  #include <boost/thread/synchronized_value.hpp>
405  namespace boost
406  {
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);
410  #endif
411  }
412
413[endsect]
414[endsect]
415
416