3 * Author: Lukas Krejci <krejci.l@centrum.cz>, (C) 2008
4 * Copyright: See COPYING file that comes with this distribution
7 #ifndef BEACON_SYNCHRONIZER_H
8 #define BEACON_SYNCHRONIZER_H
10 #include <beacon/detail/quick_wait.hpp>
18 * This class is used to synchronize access to 2 objects
19 * that need to ensure that each other is available in a
20 * multithread safe manner.
21 * Do not use it directly, Use {@link create_synchronizers}
27 synchronizer() : _active(2), _locked(AO_TS_INITIALIZER
) {
43 * @return the number of active delegates left after this call.
45 unsigned release_one() {
46 unsigned left
= --_active
;
55 * @return the number of active delegates. Never returns 0, because
56 * this instance automatically destroys itself when the delegate count
65 synchronizer(synchronizer
const &) : _active(2), _locked(AO_TS_INITIALIZER
) {}
66 synchronizer
const & operator=(synchronizer
const &) {
71 volatile AO_TS_t _locked
;
77 * Two instances of this class are returned from {@link create_synchronizers} function.
78 * Each such delegate is intended to be used by one of the objects passed to the function.
79 * A delegate is intended to be used from a single thread.
81 template<typename OtherType
>
82 class synchronizer_delegate
{
85 synchronizer_delegate(detail::synchronizer
& sync
, OtherType other
) :
94 ~synchronizer_delegate() {
99 * Locks the synchronizer. If the other object from the pair
100 * created by the {@link create_synchronizers} function call this method
101 * on its synchronizer_delegate, it will block until this object calls
112 * Unlocks the synchronizer. It is an error to call this if the synchronizer
113 * has not been locked before.
123 * Releases this delegate from the synchronizer. Any subsequent calls to
124 * any of this instance's methods will have no effect. {@link other} method
125 * will return 0. If this delegate locked the synchronizer before, it is
126 * silently unlocked by this method, i.e. there's no need to call unlock
127 * after release (it would have no effect anyway).
134 //if release_one returns 0, it destroyed and unlocked itself
136 if (_sync
.release_one() > 0) {
145 * @return the "other" object that uses the same synchronizer or null if the
146 * object no longer exists.
149 if (_bound
&& _sync
.active() > 1) {
157 synchronizer_delegate(synchronizer_delegate
<OtherType
> const &) {}
158 synchronizer_delegate
<OtherType
> const & operator=(synchronizer_delegate
<OtherType
> const &){}
160 detail::synchronizer
& _sync
;
167 * This function creates two {@link synchronizer_delegate}s each intended to be used
168 * by 1 of the objects passed.
170 template<typename T1
, typename T2
>
171 std::pair
<synchronizer_delegate
<T2
> *, synchronizer_delegate
<T1
> * > create_synchronizers(
175 detail::synchronizer
* sync
= new detail::synchronizer
;
177 return std::pair
<synchronizer_delegate
<T2
> *, synchronizer_delegate
<T1
> * >(
178 new synchronizer_delegate
<T2
>(*sync
, o2
),
179 new synchronizer_delegate
<T1
>(*sync
, o1
));