with_lock_guard.hpp 5.9 KB

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