123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- [/
- / 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: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() noexcept(is_nothrow_default_constructible<T>::value);
- synchronized_value(T const& other) noexcept(is_nothrow_copy_constructible<T>::value);
- synchronized_value(T&& other) noexcept(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() noexcept(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) noexcept(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) noexcept(is_nothrow_move_constructible<T>::value);
- [variablelist
- [[Requires:] [`T` is `MoveConstructible `.]]
- [[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 `MoveConstructible `.]]
- [[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 `Assignable`.]]
- [[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 `Assignable`.]]
- [[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 `Assignable`.]]
- [[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]
|