Chris@102: // (C) Copyright 2013 Ruslan Baratov Chris@102: // Copyright (C) 2014 Vicente J. Botet Escriba Chris@102: // Chris@102: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@102: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: Chris@102: // See www.boost.org/libs/thread for documentation. Chris@102: Chris@102: #ifndef BOOST_THREAD_WITH_LOCK_GUARD_HPP Chris@102: #define BOOST_THREAD_WITH_LOCK_GUARD_HPP Chris@102: Chris@102: #include Chris@102: #include Chris@102: //#include Chris@102: Chris@102: namespace boost { Chris@102: Chris@102: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ Chris@102: !defined(BOOST_NO_CXX11_DECLTYPE) && \ Chris@102: !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) Chris@102: Chris@102: /** Chris@102: * Utility to run functions in scope protected by mutex. Chris@102: * Chris@102: * Examples: Chris@102: * Chris@102: * int func(int, int&); Chris@102: * boost::mutex m; Chris@102: * int a; Chris@102: * int result = boost::with_lock_guard(m, func, 1, boost::ref(a)); Chris@102: * Chris@102: * // using boost::bind Chris@102: * int result = boost::with_lock_guard( Chris@102: * m, boost::bind(func, 2, boost::ref(a)) Chris@102: * ); Chris@102: * Chris@102: * // using lambda Chris@102: * int a; Chris@102: * int result = boost::with_lock_guard( Chris@102: * m, Chris@102: * [&a](int x) { Chris@102: * a = 3; Chris@102: * return x + 4; Chris@102: * }, Chris@102: * 5 Chris@102: * ); Chris@102: */ Chris@102: template Chris@102: typename boost::result_of::type with_lock_guard( Chris@102: Lockable& m, Chris@102: BOOST_FWD_REF(Function) func, Chris@102: BOOST_FWD_REF(Args)... args Chris@102: ) //-> decltype(func(boost::forward(args)...)) Chris@102: { Chris@102: boost::lock_guard lock(m); Chris@102: return func(boost::forward(args)...); Chris@102: } Chris@102: Chris@102: #else Chris@102: Chris@102: // Workaround versions for compilers without c++11 variadic templates support. Chris@102: // (function arguments limit: 4) Chris@102: // (for lambda support define BOOST_RESULT_OF_USE_DECLTYPE may be needed) Chris@102: Chris@102: template Chris@102: typename boost::result_of::type with_lock_guard( Chris@102: Lockable& m, Chris@102: BOOST_FWD_REF(Func) func Chris@102: ) { Chris@102: boost::lock_guard lock(m); Chris@102: return func(); Chris@102: } Chris@102: Chris@102: template Chris@102: typename boost::result_of::type with_lock_guard( Chris@102: Lockable& m, Chris@102: BOOST_FWD_REF(Func) func, Chris@102: BOOST_FWD_REF(Arg) arg Chris@102: ) { Chris@102: boost::lock_guard lock(m); Chris@102: return func( Chris@102: boost::forward(arg) Chris@102: ); Chris@102: } Chris@102: Chris@102: template Chris@102: typename boost::result_of::type with_lock_guard( Chris@102: Lockable& m, Chris@102: BOOST_FWD_REF(Func) func, Chris@102: BOOST_FWD_REF(Arg1) arg1, Chris@102: BOOST_FWD_REF(Arg2) arg2 Chris@102: ) { Chris@102: boost::lock_guard lock(m); Chris@102: return func( Chris@102: boost::forward(arg1), Chris@102: boost::forward(arg2) Chris@102: ); Chris@102: } Chris@102: Chris@102: template Chris@102: typename boost::result_of::type with_lock_guard( Chris@102: Lockable& m, Chris@102: BOOST_FWD_REF(Func) func, Chris@102: BOOST_FWD_REF(Arg1) arg1, Chris@102: BOOST_FWD_REF(Arg2) arg2, Chris@102: BOOST_FWD_REF(Arg3) arg3 Chris@102: ) { Chris@102: boost::lock_guard lock(m); Chris@102: return func( Chris@102: boost::forward(arg1), Chris@102: boost::forward(arg2), Chris@102: boost::forward(arg3) Chris@102: ); Chris@102: } Chris@102: Chris@102: template < Chris@102: class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4 Chris@102: > Chris@102: typename boost::result_of::type with_lock_guard( Chris@102: Lockable& m, Chris@102: BOOST_FWD_REF(Func) func, Chris@102: BOOST_FWD_REF(Arg1) arg1, Chris@102: BOOST_FWD_REF(Arg2) arg2, Chris@102: BOOST_FWD_REF(Arg3) arg3, Chris@102: BOOST_FWD_REF(Arg4) arg4 Chris@102: ) { Chris@102: boost::lock_guard lock(m); Chris@102: return func( Chris@102: boost::forward(arg1), Chris@102: boost::forward(arg2), Chris@102: boost::forward(arg3), Chris@102: boost::forward(arg4) Chris@102: ); Chris@102: } Chris@102: Chris@102: // overloads for function pointer Chris@102: // (if argument is not function pointer, static assert will trigger) Chris@102: template Chris@102: typename boost::result_of< Chris@102: typename boost::add_pointer::type() Chris@102: >::type with_lock_guard( Chris@102: Lockable& m, Chris@102: Func* func Chris@102: ) { Chris@102: BOOST_STATIC_ASSERT(boost::is_function::value); Chris@102: Chris@102: boost::lock_guard lock(m); Chris@102: return func(); Chris@102: } Chris@102: Chris@102: template Chris@102: typename boost::result_of< Chris@102: typename boost::add_pointer::type(Arg) Chris@102: >::type with_lock_guard( Chris@102: Lockable& m, Chris@102: Func* func, Chris@102: BOOST_FWD_REF(Arg) arg Chris@102: ) { Chris@102: BOOST_STATIC_ASSERT(boost::is_function::value); Chris@102: Chris@102: boost::lock_guard lock(m); Chris@102: return func( Chris@102: boost::forward(arg) Chris@102: ); Chris@102: } Chris@102: Chris@102: template Chris@102: typename boost::result_of< Chris@102: typename boost::add_pointer::type(Arg1, Arg2) Chris@102: >::type with_lock_guard( Chris@102: Lockable& m, Chris@102: Func* func, Chris@102: BOOST_FWD_REF(Arg1) arg1, Chris@102: BOOST_FWD_REF(Arg2) arg2 Chris@102: ) { Chris@102: BOOST_STATIC_ASSERT(boost::is_function::value); Chris@102: Chris@102: boost::lock_guard lock(m); Chris@102: return func( Chris@102: boost::forward(arg1), Chris@102: boost::forward(arg2) Chris@102: ); Chris@102: } Chris@102: Chris@102: template Chris@102: typename boost::result_of< Chris@102: typename boost::add_pointer::type(Arg1, Arg2, Arg3) Chris@102: >::type with_lock_guard( Chris@102: Lockable& m, Chris@102: Func* func, Chris@102: BOOST_FWD_REF(Arg1) arg1, Chris@102: BOOST_FWD_REF(Arg2) arg2, Chris@102: BOOST_FWD_REF(Arg3) arg3 Chris@102: ) { Chris@102: BOOST_STATIC_ASSERT(boost::is_function::value); Chris@102: Chris@102: boost::lock_guard lock(m); Chris@102: return func( Chris@102: boost::forward(arg1), Chris@102: boost::forward(arg2), Chris@102: boost::forward(arg3) Chris@102: ); Chris@102: } Chris@102: Chris@102: template < Chris@102: class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4 Chris@102: > Chris@102: typename boost::result_of< Chris@102: typename boost::add_pointer::type(Arg1, Arg2, Arg3, Arg4) Chris@102: >::type with_lock_guard( Chris@102: Lockable& m, Chris@102: Func* func, Chris@102: BOOST_FWD_REF(Arg1) arg1, Chris@102: BOOST_FWD_REF(Arg2) arg2, Chris@102: BOOST_FWD_REF(Arg3) arg3, Chris@102: BOOST_FWD_REF(Arg4) arg4 Chris@102: ) { Chris@102: BOOST_STATIC_ASSERT(boost::is_function::value); Chris@102: Chris@102: boost::lock_guard lock(m); Chris@102: return func( Chris@102: boost::forward(arg1), Chris@102: boost::forward(arg2), Chris@102: boost::forward(arg3), Chris@102: boost::forward(arg4) Chris@102: ); Chris@102: } Chris@102: Chris@102: #endif Chris@102: Chris@102: } // namespace boost Chris@102: Chris@102: #endif // BOOST_THREAD_WITH_LOCK_GUARD_HPP Chris@102: