blob: 2826282e1831d439d942cc050d616ef25a3b52be [file] [log] [blame]
[/
/ 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]