Chris@102
|
1 // (C) Copyright 2013 Ruslan Baratov
|
Chris@102
|
2 // Copyright (C) 2014 Vicente J. Botet Escriba
|
Chris@102
|
3 //
|
Chris@102
|
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@102
|
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
6
|
Chris@102
|
7 // See www.boost.org/libs/thread for documentation.
|
Chris@102
|
8
|
Chris@102
|
9 #ifndef BOOST_THREAD_WITH_LOCK_GUARD_HPP
|
Chris@102
|
10 #define BOOST_THREAD_WITH_LOCK_GUARD_HPP
|
Chris@102
|
11
|
Chris@102
|
12 #include <boost/thread/lock_guard.hpp>
|
Chris@102
|
13 #include <boost/utility/result_of.hpp>
|
Chris@102
|
14 //#include <boost/thread/detail/invoke.hpp>
|
Chris@102
|
15
|
Chris@102
|
16 namespace boost {
|
Chris@102
|
17
|
Chris@102
|
18 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
Chris@102
|
19 !defined(BOOST_NO_CXX11_DECLTYPE) && \
|
Chris@102
|
20 !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
|
Chris@102
|
21
|
Chris@102
|
22 /**
|
Chris@102
|
23 * Utility to run functions in scope protected by mutex.
|
Chris@102
|
24 *
|
Chris@102
|
25 * Examples:
|
Chris@102
|
26 *
|
Chris@102
|
27 * int func(int, int&);
|
Chris@102
|
28 * boost::mutex m;
|
Chris@102
|
29 * int a;
|
Chris@102
|
30 * int result = boost::with_lock_guard(m, func, 1, boost::ref(a));
|
Chris@102
|
31 *
|
Chris@102
|
32 * // using boost::bind
|
Chris@102
|
33 * int result = boost::with_lock_guard(
|
Chris@102
|
34 * m, boost::bind(func, 2, boost::ref(a))
|
Chris@102
|
35 * );
|
Chris@102
|
36 *
|
Chris@102
|
37 * // using lambda
|
Chris@102
|
38 * int a;
|
Chris@102
|
39 * int result = boost::with_lock_guard(
|
Chris@102
|
40 * m,
|
Chris@102
|
41 * [&a](int x) {
|
Chris@102
|
42 * a = 3;
|
Chris@102
|
43 * return x + 4;
|
Chris@102
|
44 * },
|
Chris@102
|
45 * 5
|
Chris@102
|
46 * );
|
Chris@102
|
47 */
|
Chris@102
|
48 template <class Lockable, class Function, class... Args>
|
Chris@102
|
49 typename boost::result_of<Function(Args...)>::type with_lock_guard(
|
Chris@102
|
50 Lockable& m,
|
Chris@102
|
51 BOOST_FWD_REF(Function) func,
|
Chris@102
|
52 BOOST_FWD_REF(Args)... args
|
Chris@102
|
53 ) //-> decltype(func(boost::forward<Args>(args)...))
|
Chris@102
|
54 {
|
Chris@102
|
55 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
56 return func(boost::forward<Args>(args)...);
|
Chris@102
|
57 }
|
Chris@102
|
58
|
Chris@102
|
59 #else
|
Chris@102
|
60
|
Chris@102
|
61 // Workaround versions for compilers without c++11 variadic templates support.
|
Chris@102
|
62 // (function arguments limit: 4)
|
Chris@102
|
63 // (for lambda support define BOOST_RESULT_OF_USE_DECLTYPE may be needed)
|
Chris@102
|
64
|
Chris@102
|
65 template <class Lockable, class Func>
|
Chris@102
|
66 typename boost::result_of<Func()>::type with_lock_guard(
|
Chris@102
|
67 Lockable& m,
|
Chris@102
|
68 BOOST_FWD_REF(Func) func
|
Chris@102
|
69 ) {
|
Chris@102
|
70 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
71 return func();
|
Chris@102
|
72 }
|
Chris@102
|
73
|
Chris@102
|
74 template <class Lockable, class Func, class Arg>
|
Chris@102
|
75 typename boost::result_of<Func(Arg)>::type with_lock_guard(
|
Chris@102
|
76 Lockable& m,
|
Chris@102
|
77 BOOST_FWD_REF(Func) func,
|
Chris@102
|
78 BOOST_FWD_REF(Arg) arg
|
Chris@102
|
79 ) {
|
Chris@102
|
80 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
81 return func(
|
Chris@102
|
82 boost::forward<Arg>(arg)
|
Chris@102
|
83 );
|
Chris@102
|
84 }
|
Chris@102
|
85
|
Chris@102
|
86 template <class Lockable, class Func, class Arg1, class Arg2>
|
Chris@102
|
87 typename boost::result_of<Func(Arg1, Arg2)>::type with_lock_guard(
|
Chris@102
|
88 Lockable& m,
|
Chris@102
|
89 BOOST_FWD_REF(Func) func,
|
Chris@102
|
90 BOOST_FWD_REF(Arg1) arg1,
|
Chris@102
|
91 BOOST_FWD_REF(Arg2) arg2
|
Chris@102
|
92 ) {
|
Chris@102
|
93 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
94 return func(
|
Chris@102
|
95 boost::forward<Arg1>(arg1),
|
Chris@102
|
96 boost::forward<Arg2>(arg2)
|
Chris@102
|
97 );
|
Chris@102
|
98 }
|
Chris@102
|
99
|
Chris@102
|
100 template <class Lockable, class Func, class Arg1, class Arg2, class Arg3>
|
Chris@102
|
101 typename boost::result_of<Func(Arg1, Arg2, Arg3)>::type with_lock_guard(
|
Chris@102
|
102 Lockable& m,
|
Chris@102
|
103 BOOST_FWD_REF(Func) func,
|
Chris@102
|
104 BOOST_FWD_REF(Arg1) arg1,
|
Chris@102
|
105 BOOST_FWD_REF(Arg2) arg2,
|
Chris@102
|
106 BOOST_FWD_REF(Arg3) arg3
|
Chris@102
|
107 ) {
|
Chris@102
|
108 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
109 return func(
|
Chris@102
|
110 boost::forward<Arg1>(arg1),
|
Chris@102
|
111 boost::forward<Arg2>(arg2),
|
Chris@102
|
112 boost::forward<Arg3>(arg3)
|
Chris@102
|
113 );
|
Chris@102
|
114 }
|
Chris@102
|
115
|
Chris@102
|
116 template <
|
Chris@102
|
117 class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4
|
Chris@102
|
118 >
|
Chris@102
|
119 typename boost::result_of<Func(Arg1, Arg2, Arg3, Arg4)>::type with_lock_guard(
|
Chris@102
|
120 Lockable& m,
|
Chris@102
|
121 BOOST_FWD_REF(Func) func,
|
Chris@102
|
122 BOOST_FWD_REF(Arg1) arg1,
|
Chris@102
|
123 BOOST_FWD_REF(Arg2) arg2,
|
Chris@102
|
124 BOOST_FWD_REF(Arg3) arg3,
|
Chris@102
|
125 BOOST_FWD_REF(Arg4) arg4
|
Chris@102
|
126 ) {
|
Chris@102
|
127 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
128 return func(
|
Chris@102
|
129 boost::forward<Arg1>(arg1),
|
Chris@102
|
130 boost::forward<Arg2>(arg2),
|
Chris@102
|
131 boost::forward<Arg3>(arg3),
|
Chris@102
|
132 boost::forward<Arg4>(arg4)
|
Chris@102
|
133 );
|
Chris@102
|
134 }
|
Chris@102
|
135
|
Chris@102
|
136 // overloads for function pointer
|
Chris@102
|
137 // (if argument is not function pointer, static assert will trigger)
|
Chris@102
|
138 template <class Lockable, class Func>
|
Chris@102
|
139 typename boost::result_of<
|
Chris@102
|
140 typename boost::add_pointer<Func>::type()
|
Chris@102
|
141 >::type with_lock_guard(
|
Chris@102
|
142 Lockable& m,
|
Chris@102
|
143 Func* func
|
Chris@102
|
144 ) {
|
Chris@102
|
145 BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
Chris@102
|
146
|
Chris@102
|
147 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
148 return func();
|
Chris@102
|
149 }
|
Chris@102
|
150
|
Chris@102
|
151 template <class Lockable, class Func, class Arg>
|
Chris@102
|
152 typename boost::result_of<
|
Chris@102
|
153 typename boost::add_pointer<Func>::type(Arg)
|
Chris@102
|
154 >::type with_lock_guard(
|
Chris@102
|
155 Lockable& m,
|
Chris@102
|
156 Func* func,
|
Chris@102
|
157 BOOST_FWD_REF(Arg) arg
|
Chris@102
|
158 ) {
|
Chris@102
|
159 BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
Chris@102
|
160
|
Chris@102
|
161 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
162 return func(
|
Chris@102
|
163 boost::forward<Arg>(arg)
|
Chris@102
|
164 );
|
Chris@102
|
165 }
|
Chris@102
|
166
|
Chris@102
|
167 template <class Lockable, class Func, class Arg1, class Arg2>
|
Chris@102
|
168 typename boost::result_of<
|
Chris@102
|
169 typename boost::add_pointer<Func>::type(Arg1, Arg2)
|
Chris@102
|
170 >::type with_lock_guard(
|
Chris@102
|
171 Lockable& m,
|
Chris@102
|
172 Func* func,
|
Chris@102
|
173 BOOST_FWD_REF(Arg1) arg1,
|
Chris@102
|
174 BOOST_FWD_REF(Arg2) arg2
|
Chris@102
|
175 ) {
|
Chris@102
|
176 BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
Chris@102
|
177
|
Chris@102
|
178 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
179 return func(
|
Chris@102
|
180 boost::forward<Arg1>(arg1),
|
Chris@102
|
181 boost::forward<Arg2>(arg2)
|
Chris@102
|
182 );
|
Chris@102
|
183 }
|
Chris@102
|
184
|
Chris@102
|
185 template <class Lockable, class Func, class Arg1, class Arg2, class Arg3>
|
Chris@102
|
186 typename boost::result_of<
|
Chris@102
|
187 typename boost::add_pointer<Func>::type(Arg1, Arg2, Arg3)
|
Chris@102
|
188 >::type with_lock_guard(
|
Chris@102
|
189 Lockable& m,
|
Chris@102
|
190 Func* func,
|
Chris@102
|
191 BOOST_FWD_REF(Arg1) arg1,
|
Chris@102
|
192 BOOST_FWD_REF(Arg2) arg2,
|
Chris@102
|
193 BOOST_FWD_REF(Arg3) arg3
|
Chris@102
|
194 ) {
|
Chris@102
|
195 BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
Chris@102
|
196
|
Chris@102
|
197 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
198 return func(
|
Chris@102
|
199 boost::forward<Arg1>(arg1),
|
Chris@102
|
200 boost::forward<Arg2>(arg2),
|
Chris@102
|
201 boost::forward<Arg3>(arg3)
|
Chris@102
|
202 );
|
Chris@102
|
203 }
|
Chris@102
|
204
|
Chris@102
|
205 template <
|
Chris@102
|
206 class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4
|
Chris@102
|
207 >
|
Chris@102
|
208 typename boost::result_of<
|
Chris@102
|
209 typename boost::add_pointer<Func>::type(Arg1, Arg2, Arg3, Arg4)
|
Chris@102
|
210 >::type with_lock_guard(
|
Chris@102
|
211 Lockable& m,
|
Chris@102
|
212 Func* func,
|
Chris@102
|
213 BOOST_FWD_REF(Arg1) arg1,
|
Chris@102
|
214 BOOST_FWD_REF(Arg2) arg2,
|
Chris@102
|
215 BOOST_FWD_REF(Arg3) arg3,
|
Chris@102
|
216 BOOST_FWD_REF(Arg4) arg4
|
Chris@102
|
217 ) {
|
Chris@102
|
218 BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
Chris@102
|
219
|
Chris@102
|
220 boost::lock_guard<Lockable> lock(m);
|
Chris@102
|
221 return func(
|
Chris@102
|
222 boost::forward<Arg1>(arg1),
|
Chris@102
|
223 boost::forward<Arg2>(arg2),
|
Chris@102
|
224 boost::forward<Arg3>(arg3),
|
Chris@102
|
225 boost::forward<Arg4>(arg4)
|
Chris@102
|
226 );
|
Chris@102
|
227 }
|
Chris@102
|
228
|
Chris@102
|
229 #endif
|
Chris@102
|
230
|
Chris@102
|
231 } // namespace boost
|
Chris@102
|
232
|
Chris@102
|
233 #endif // BOOST_THREAD_WITH_LOCK_GUARD_HPP
|
Chris@102
|
234
|