]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Distributed under the Boost Software License, Version 1.0. (See |
2 | // accompanying file LICENSE_1_0.txt or copy at | |
3 | // http://www.boost.org/LICENSE_1_0.txt) | |
4 | // (C) Copyright 2008-2009,2012 Vicente J. Botet Escriba | |
5 | ||
6 | #ifndef BOOST_THREAD_STRICT_LOCK_HPP | |
7 | #define BOOST_THREAD_STRICT_LOCK_HPP | |
8 | ||
9 | #include <boost/thread/detail/config.hpp> | |
10 | #include <boost/thread/detail/delete.hpp> | |
11 | #include <boost/thread/detail/lockable_wrapper.hpp> | |
12 | #include <boost/thread/lock_options.hpp> | |
13 | #include <boost/thread/lock_traits.hpp> | |
14 | #include <boost/thread/lockable_traits.hpp> | |
15 | #include <boost/thread/lockable_concepts.hpp> | |
16 | #include <boost/thread/lock_concepts.hpp> | |
17 | #include <boost/thread/exceptions.hpp> | |
18 | #include <boost/throw_exception.hpp> | |
19 | ||
20 | #include <boost/config/abi_prefix.hpp> | |
21 | ||
22 | namespace boost | |
23 | { | |
24 | ||
25 | ||
26 | //[strict_lock | |
27 | template <typename Lockable> | |
28 | class strict_lock | |
29 | { | |
30 | ||
31 | BOOST_CONCEPT_ASSERT(( BasicLockable<Lockable> )); | |
32 | public: | |
33 | typedef Lockable mutex_type; | |
34 | ||
35 | // construct/copy/destroy: | |
36 | ||
37 | BOOST_THREAD_NO_COPYABLE( strict_lock) | |
38 | ||
39 | /** | |
40 | * Constructor from a mutex reference. | |
41 | * | |
42 | * @param mtx the mutex to lock. | |
43 | * | |
44 | * __Effects: Stores a reference to the mutex to lock and locks it. | |
45 | * __Throws: Any exception BasicMutex::lock() can throw. | |
46 | */ | |
47 | explicit strict_lock(mutex_type& mtx) : | |
48 | mtx_(mtx) | |
49 | { | |
50 | mtx.lock(); | |
51 | } /*< locks on construction >*/ | |
52 | ||
53 | ||
54 | #if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST | |
55 | strict_lock(std::initializer_list<thread_detail::lockable_wrapper<Lockable> > l_) : | |
56 | mtx_(*(const_cast<thread_detail::lockable_wrapper<Lockable>*>(l_.begin())->m)) | |
57 | { | |
58 | mtx_.lock(); | |
59 | } | |
60 | #endif | |
61 | ||
62 | /** | |
63 | * Destructor | |
64 | * | |
65 | * __Effects: unlocks the stored mutex. | |
66 | * | |
67 | * __Throws | |
68 | */ | |
69 | ~strict_lock() | |
70 | { | |
71 | mtx_.unlock(); | |
72 | } /*< unlocks on destruction >*/ | |
73 | ||
74 | ||
75 | // observers | |
76 | ||
77 | /** | |
78 | * @return the owned mutex. | |
79 | */ | |
80 | mutex_type* mutex() const BOOST_NOEXCEPT | |
81 | { | |
82 | return &mtx_; | |
83 | } | |
84 | ||
85 | /** | |
86 | * @return whether this lock is locking a mutex. | |
87 | */ | |
88 | bool owns_lock() const BOOST_NOEXCEPT | |
89 | { | |
90 | return true; | |
91 | } | |
92 | ||
93 | /** | |
94 | * @return whether this lock is locking that mutex. | |
95 | */ | |
96 | bool owns_lock(const mutex_type* l) const BOOST_NOEXCEPT | |
97 | { | |
98 | return l == mutex(); | |
99 | } /*< strict locks specific function >*/ | |
100 | ||
101 | //BOOST_ADRESS_OF_DELETE(strict_lock) /*< disable aliasing >*/ | |
102 | //BOOST_HEAP_ALLOCATION_DELETE(strict_lock) /*< disable heap allocation >*/ | |
103 | ||
104 | /*< no possibility to unlock >*/ | |
105 | ||
106 | private: | |
107 | mutex_type& mtx_; | |
108 | }; | |
109 | //] | |
110 | template <typename Lockable> | |
111 | struct is_strict_lock_sur_parole<strict_lock<Lockable> > : true_type | |
112 | { | |
113 | }; | |
114 | ||
115 | /** | |
116 | * A nested strict lock is a scoped lock guard ensuring the mutex is locked on its | |
117 | * scope, by taking ownership of an nesting lock, locking the mutex on construction if not already locked | |
118 | * and restoring the ownership to the nesting lock on destruction. | |
119 | */ | |
120 | //[nested_strict_lock | |
121 | template <typename Lock> | |
122 | class nested_strict_lock | |
123 | { | |
124 | BOOST_CONCEPT_ASSERT(( BasicLock<Lock> )); /*< The Lock must be a movable lock >*/ | |
125 | public: | |
126 | typedef typename Lock::mutex_type mutex_type; /*< Name the lockable type locked by Lock >*/ | |
127 | ||
128 | BOOST_THREAD_NO_COPYABLE( nested_strict_lock) | |
129 | ||
130 | /** | |
131 | * Constructor from a nesting @c Lock. | |
132 | * | |
133 | * @param lk the nesting lock | |
134 | * | |
135 | * __Requires: <c>lk.mutex() != null_ptr</c> | |
136 | * __Effects: Stores the reference to the lock parameter and takes ownership on it. | |
137 | * If the lock doesn't owns the mutex @c mtx lock it. | |
138 | * __Postconditions: @c owns_lock(lk.mutex()) | |
139 | * __StrongException | |
140 | * __Throws: | |
141 | * | |
142 | * - lock_error when BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined and lk.mutex() == null_ptr | |
143 | * | |
144 | * - Any exception that @c lk.lock() can throw. | |
145 | * | |
146 | */ | |
147 | explicit nested_strict_lock(Lock& lk) : | |
148 | lk_(lk) /*< Store reference to lk >*/ | |
149 | { | |
150 | /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/ | |
151 | BOOST_THREAD_ASSERT_PRECONDITION( lk.mutex() != 0, | |
152 | lock_error() | |
153 | ); | |
154 | if (!lk.owns_lock()) lk.lock(); /*< ensures it is locked >*/ | |
155 | tmp_lk_ = move(lk); /*< Move ownership to temporary lk >*/ | |
156 | } | |
157 | ||
158 | #if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST | |
159 | nested_strict_lock(std::initializer_list<thread_detail::lockable_wrapper<Lock> > l_) : | |
160 | lk_(*(const_cast<thread_detail::lockable_wrapper<Lock>*>(l_.begin())->m)) | |
161 | { | |
162 | /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/ | |
163 | BOOST_THREAD_ASSERT_PRECONDITION( lk_.mutex() != 0, | |
164 | lock_error() | |
165 | ); | |
166 | if (!lk_.owns_lock()) lk_.lock(); /*< ensures it is locked >*/ | |
167 | tmp_lk_ = move(lk_); /*< Move ownership to temporary lk >*/ | |
168 | } | |
169 | #endif | |
170 | ||
171 | /** | |
172 | * Destructor | |
173 | * | |
174 | * __Effects: Restores ownership to the nesting lock. | |
175 | */ | |
176 | ~nested_strict_lock()BOOST_NOEXCEPT | |
177 | { | |
178 | lk_ = move(tmp_lk_); /*< Move ownership to nesting lock >*/ | |
179 | } | |
180 | ||
181 | // observers | |
182 | /** | |
183 | * return @c the owned mutex. | |
184 | */ | |
185 | mutex_type* mutex() const BOOST_NOEXCEPT | |
186 | { | |
187 | return tmp_lk_.mutex(); | |
188 | } | |
189 | ||
190 | /** | |
191 | * @return whether this lock is locking a mutex. | |
192 | */ | |
193 | bool owns_lock() const BOOST_NOEXCEPT | |
194 | { | |
195 | return true; | |
196 | } | |
197 | ||
198 | /** | |
199 | * @return whether if this lock is locking that mutex. | |
200 | */ | |
201 | bool owns_lock(mutex_type const* l) const BOOST_NOEXCEPT | |
202 | { | |
203 | return l == mutex(); | |
204 | } | |
205 | ||
206 | //BOOST_ADRESS_OF_DELETE(nested_strict_lock) | |
207 | //BOOST_HEAP_ALLOCATEION_DELETE(nested_strict_lock) | |
208 | ||
209 | private: | |
210 | Lock& lk_; | |
211 | Lock tmp_lk_; | |
212 | }; | |
213 | //] | |
214 | ||
215 | template <typename Lock> | |
216 | struct is_strict_lock_sur_parole<nested_strict_lock<Lock> > : true_type | |
217 | { | |
218 | }; | |
219 | ||
220 | #if ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK | |
221 | template <typename Lockable> | |
222 | strict_lock<Lockable> make_strict_lock(Lockable& mtx) | |
223 | { | |
224 | return { thread_detail::lockable_wrapper<Lockable>(mtx) }; | |
225 | } | |
226 | template <typename Lock> | |
227 | nested_strict_lock<Lock> make_nested_strict_lock(Lock& lk) | |
228 | { | |
229 | return { thread_detail::lockable_wrapper<Lock>(lk) }; | |
230 | } | |
231 | #endif | |
232 | } | |
233 | #include <boost/config/abi_suffix.hpp> | |
234 | ||
235 | #endif |