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