Ticket #9058: with_lock_guard.2.hpp

File with_lock_guard.2.hpp, 3.3 KB (added by ruslan_baratov@…, 9 years ago)

update implementation: forward for compiler without c++11 variadic templates

Line 
1// (C) Copyright 2013 Ruslan Baratov
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6// See www.boost.org/libs/thread for documentation.
7
8#ifndef BOOST_THREAD_WITH_LOCK_GUARD_HPP
9#define BOOST_THREAD_WITH_LOCK_GUARD_HPP
10
11#include <boost/thread/lock_guard.hpp>
12#include <boost/utility/result_of.hpp>
13
14namespace boost {
15
16#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
17
18/**
19 * Utility to run functions in scope protected by mutex.
20 *
21 * Examples:
22 *
23 * int func(int, int&);
24 * boost::mutex m;
25 * int a;
26 * int result = boost::with_lock_guard(m, func, 1, boost::ref(a));
27 *
28 * // using boost::bind
29 * int result = boost::with_lock_guard(
30 * m, boost::bind(func, 2, boost::ref(a))
31 * );
32 *
33 * // using lambda
34 * int a;
35 * int result = boost::with_lock_guard(
36 * m,
37 * [&a](int x) {
38 * a = 3;
39 * return x + 4;
40 * },
41 * 5
42 * );
43 */
44template <class Lockable, class Function, class... Args>
45auto with_lock_guard(
46 Lockable& m,
47 BOOST_FWD_REF(Function) f,
48 BOOST_FWD_REF(Args)... args
49) -> decltype(f(boost::forward<Args>(args)...)) {
50 boost::lock_guard<Lockable> lock(m);
51 return f(boost::forward<Args>(args)...);
52}
53
54#else
55
56// Workaround versions for compilers without c++11 support.
57// (function arguments limit: 4, no lambda support)
58
59template <class Lockable, class Func>
60typename boost::result_of<Func()>::type with_lock_guard(
61 Lockable& m,
62 Func func
63) {
64 boost::lock_guard<Lockable> lock(m);
65 return func();
66}
67
68template <class Lockable, class Func, class Arg>
69typename boost::result_of<Func(Arg)>::type with_lock_guard(
70 Lockable& m,
71 Func func,
72 BOOST_FWD_REF(Arg) arg
73) {
74 boost::lock_guard<Lockable> lock(m);
75 return func(
76 boost::forward<Arg>(arg)
77 );
78}
79
80template <class Lockable, class Func, class Arg1, class Arg2>
81typename boost::result_of<Func(Arg1, Arg2)>::type with_lock_guard(
82 Lockable& m,
83 Func func,
84 BOOST_FWD_REF(Arg1) arg1,
85 BOOST_FWD_REF(Arg2) arg2
86) {
87 boost::lock_guard<Lockable> lock(m);
88 return func(
89 boost::forward<Arg1>(arg1),
90 boost::forward<Arg2>(arg2)
91 );
92}
93
94template <class Lockable, class Func, class Arg1, class Arg2, class Arg3>
95typename boost::result_of<Func(Arg1, Arg2, Arg3)>::type with_lock_guard(
96 Lockable& m,
97 Func func,
98 BOOST_FWD_REF(Arg1) arg1,
99 BOOST_FWD_REF(Arg2) arg2,
100 BOOST_FWD_REF(Arg3) arg3
101) {
102 boost::lock_guard<Lockable> lock(m);
103 return func(
104 boost::forward<Arg1>(arg1),
105 boost::forward<Arg2>(arg2),
106 boost::forward<Arg3>(arg3)
107 );
108}
109
110template <
111 class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4
112>
113typename boost::result_of<Func(Arg1, Arg2, Arg3, Arg4)>::type with_lock_guard(
114 Lockable& m,
115 Func func,
116 BOOST_FWD_REF(Arg1) arg1,
117 BOOST_FWD_REF(Arg2) arg2,
118 BOOST_FWD_REF(Arg3) arg3,
119 BOOST_FWD_REF(Arg4) arg4
120) {
121 boost::lock_guard<Lockable> lock(m);
122 return func(
123 boost::forward<Arg1>(arg1),
124 boost::forward<Arg2>(arg2),
125 boost::forward<Arg3>(arg3),
126 boost::forward<Arg4>(arg4)
127 );
128}
129
130#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
131
132} // namespace boost
133
134#endif // BOOST_THREAD_WITH_LOCK_GUARD_HPP