mirror of
https://github.com/boostorg/thread.git
synced 2026-01-27 19:32:11 +00:00
Pulled with_lock_guard patch.
This commit is contained in:
@@ -1115,6 +1115,44 @@ object passed to the constructor.]]
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:with_lock_guard With Lock Guard]
|
||||
|
||||
// #include <boost/thread/with_lock_guard.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class Lockable, class Function, class... Args>
|
||||
auto with_lock_guard(Lockable& m, Function&& func, Args&&... args) -> decltype(func(boost::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
[section:with_lock_guard Non Member Function `with_lock_guard`]
|
||||
|
||||
template <class Lockable, class Function, class... Args>
|
||||
auto with_lock_guard(
|
||||
Lockable& m,
|
||||
Function&& func,
|
||||
Args&&... args
|
||||
) -> decltype(func(boost::forward<Args>(args)...));
|
||||
|
||||
[variablelist
|
||||
|
||||
[[Precondition:] [`m` must be in unlocked state]]
|
||||
[[Effects:] [call `func` in scope locked by `m`]]
|
||||
[[Returns:] [Result of `func(args...)` call]]
|
||||
[[Throws:] [Any exception thrown by the call to `m.lock` and `func(args...)`]]
|
||||
[[Postcondition:] [`m` is in unlocked state]]
|
||||
|
||||
[[Limitations:] [Without c++11 variadic templates support number of arguments is limited to `4`]]
|
||||
[[] [Without rvalue references support calling class method with `boost::bind` must be const]]
|
||||
[[] [For correct work with lambda macro `BOOST_RESULT_OF_USE_DECLTYPE` may be needed to define]]
|
||||
|
||||
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -20,24 +20,44 @@ In addition to the C++11 standard locks, Boost.Thread provides other locks and s
|
||||
|
||||
[section:with Executing Around a Function]
|
||||
|
||||
In particular, the library provides some lock factories.
|
||||
In particular, the library provides a way to lock around the execution of a function.
|
||||
|
||||
template <class Lockable, class Function>
|
||||
auto with_lock_guard(Lockable& m, Function f) -> decltype(f())
|
||||
{
|
||||
auto&& _ = boost::make_lock_guard(m);
|
||||
f();
|
||||
template <class Lockable, class Function, class... Args>
|
||||
auto with_lock_guard(
|
||||
Lockable& m,
|
||||
Function&& func,
|
||||
Args&&... args
|
||||
) -> decltype(func(boost::forward<Args>(args)...)) {
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
that can be used with regular functions:
|
||||
|
||||
that can be used as
|
||||
int func(int, int&);
|
||||
//...
|
||||
boost::mutex m;
|
||||
int a;
|
||||
int result = boost::with_lock_guard(m, func, 1, boost::ref(a));
|
||||
|
||||
int i = with_lock_guard(mtx, []()
|
||||
{
|
||||
// access the protected state
|
||||
return true;
|
||||
});
|
||||
with boost::bind:
|
||||
|
||||
int result = boost::with_lock_guard(
|
||||
m, boost::bind(func, 2, boost::ref(a))
|
||||
);
|
||||
|
||||
or with lambda expression:
|
||||
|
||||
int a;
|
||||
int result = boost::with_lock_guard(
|
||||
m,
|
||||
[&a](int x) {
|
||||
// this scope is protected by mutex m
|
||||
a = 3;
|
||||
return x + 4;
|
||||
},
|
||||
5
|
||||
);
|
||||
|
||||
[endsect] [/ With]
|
||||
|
||||
|
||||
232
include/boost/thread/with_lock_guard.hpp
Normal file
232
include/boost/thread/with_lock_guard.hpp
Normal file
@@ -0,0 +1,232 @@
|
||||
// (C) Copyright 2013 Ruslan Baratov
|
||||
// Copyright (C) 2014 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See www.boost.org/libs/thread for documentation.
|
||||
|
||||
#ifndef BOOST_THREAD_WITH_LOCK_GUARD_HPP
|
||||
#define BOOST_THREAD_WITH_LOCK_GUARD_HPP
|
||||
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/utility/result_of.hpp>
|
||||
//#include <boost/thread/detail/invoke.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
!defined(BOOST_NO_CXX11_DECLTYPE)
|
||||
|
||||
/**
|
||||
* Utility to run functions in scope protected by mutex.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* int func(int, int&);
|
||||
* boost::mutex m;
|
||||
* int a;
|
||||
* int result = boost::with_lock_guard(m, func, 1, boost::ref(a));
|
||||
*
|
||||
* // using boost::bind
|
||||
* int result = boost::with_lock_guard(
|
||||
* m, boost::bind(func, 2, boost::ref(a))
|
||||
* );
|
||||
*
|
||||
* // using lambda
|
||||
* int a;
|
||||
* int result = boost::with_lock_guard(
|
||||
* m,
|
||||
* [&a](int x) {
|
||||
* a = 3;
|
||||
* return x + 4;
|
||||
* },
|
||||
* 5
|
||||
* );
|
||||
*/
|
||||
template <class Lockable, class Function, class... Args>
|
||||
auto with_lock_guard(
|
||||
Lockable& m,
|
||||
BOOST_FWD_REF(Function) func,
|
||||
BOOST_FWD_REF(Args)... args
|
||||
) -> decltype(func(boost::forward<Args>(args)...)) {
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Workaround versions for compilers without c++11 variadic templates support.
|
||||
// (function arguments limit: 4)
|
||||
// (for lambda support define BOOST_RESULT_OF_USE_DECLTYPE may be needed)
|
||||
|
||||
template <class Lockable, class Func>
|
||||
typename boost::result_of<Func()>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
BOOST_FWD_REF(Func) func
|
||||
) {
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func();
|
||||
}
|
||||
|
||||
template <class Lockable, class Func, class Arg>
|
||||
typename boost::result_of<Func(Arg)>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
BOOST_FWD_REF(Func) func,
|
||||
BOOST_FWD_REF(Arg) arg
|
||||
) {
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(
|
||||
boost::forward<Arg>(arg)
|
||||
);
|
||||
}
|
||||
|
||||
template <class Lockable, class Func, class Arg1, class Arg2>
|
||||
typename boost::result_of<Func(Arg1, Arg2)>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
BOOST_FWD_REF(Func) func,
|
||||
BOOST_FWD_REF(Arg1) arg1,
|
||||
BOOST_FWD_REF(Arg2) arg2
|
||||
) {
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(
|
||||
boost::forward<Arg1>(arg1),
|
||||
boost::forward<Arg2>(arg2)
|
||||
);
|
||||
}
|
||||
|
||||
template <class Lockable, class Func, class Arg1, class Arg2, class Arg3>
|
||||
typename boost::result_of<Func(Arg1, Arg2, Arg3)>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
BOOST_FWD_REF(Func) func,
|
||||
BOOST_FWD_REF(Arg1) arg1,
|
||||
BOOST_FWD_REF(Arg2) arg2,
|
||||
BOOST_FWD_REF(Arg3) arg3
|
||||
) {
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(
|
||||
boost::forward<Arg1>(arg1),
|
||||
boost::forward<Arg2>(arg2),
|
||||
boost::forward<Arg3>(arg3)
|
||||
);
|
||||
}
|
||||
|
||||
template <
|
||||
class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4
|
||||
>
|
||||
typename boost::result_of<Func(Arg1, Arg2, Arg3, Arg4)>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
BOOST_FWD_REF(Func) func,
|
||||
BOOST_FWD_REF(Arg1) arg1,
|
||||
BOOST_FWD_REF(Arg2) arg2,
|
||||
BOOST_FWD_REF(Arg3) arg3,
|
||||
BOOST_FWD_REF(Arg4) arg4
|
||||
) {
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(
|
||||
boost::forward<Arg1>(arg1),
|
||||
boost::forward<Arg2>(arg2),
|
||||
boost::forward<Arg3>(arg3),
|
||||
boost::forward<Arg4>(arg4)
|
||||
);
|
||||
}
|
||||
|
||||
// overloads for function pointer
|
||||
// (if argument is not function pointer, static assert will trigger)
|
||||
template <class Lockable, class Func>
|
||||
typename boost::result_of<
|
||||
typename boost::add_pointer<Func>::type()
|
||||
>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
Func* func
|
||||
) {
|
||||
BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
||||
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func();
|
||||
}
|
||||
|
||||
template <class Lockable, class Func, class Arg>
|
||||
typename boost::result_of<
|
||||
typename boost::add_pointer<Func>::type(Arg)
|
||||
>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
Func* func,
|
||||
BOOST_FWD_REF(Arg) arg
|
||||
) {
|
||||
BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
||||
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(
|
||||
boost::forward<Arg>(arg)
|
||||
);
|
||||
}
|
||||
|
||||
template <class Lockable, class Func, class Arg1, class Arg2>
|
||||
typename boost::result_of<
|
||||
typename boost::add_pointer<Func>::type(Arg1, Arg2)
|
||||
>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
Func* func,
|
||||
BOOST_FWD_REF(Arg1) arg1,
|
||||
BOOST_FWD_REF(Arg2) arg2
|
||||
) {
|
||||
BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
||||
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(
|
||||
boost::forward<Arg1>(arg1),
|
||||
boost::forward<Arg2>(arg2)
|
||||
);
|
||||
}
|
||||
|
||||
template <class Lockable, class Func, class Arg1, class Arg2, class Arg3>
|
||||
typename boost::result_of<
|
||||
typename boost::add_pointer<Func>::type(Arg1, Arg2, Arg3)
|
||||
>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
Func* func,
|
||||
BOOST_FWD_REF(Arg1) arg1,
|
||||
BOOST_FWD_REF(Arg2) arg2,
|
||||
BOOST_FWD_REF(Arg3) arg3
|
||||
) {
|
||||
BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
||||
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(
|
||||
boost::forward<Arg1>(arg1),
|
||||
boost::forward<Arg2>(arg2),
|
||||
boost::forward<Arg3>(arg3)
|
||||
);
|
||||
}
|
||||
|
||||
template <
|
||||
class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4
|
||||
>
|
||||
typename boost::result_of<
|
||||
typename boost::add_pointer<Func>::type(Arg1, Arg2, Arg3, Arg4)
|
||||
>::type with_lock_guard(
|
||||
Lockable& m,
|
||||
Func* func,
|
||||
BOOST_FWD_REF(Arg1) arg1,
|
||||
BOOST_FWD_REF(Arg2) arg2,
|
||||
BOOST_FWD_REF(Arg3) arg3,
|
||||
BOOST_FWD_REF(Arg4) arg4
|
||||
) {
|
||||
BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
|
||||
|
||||
boost::lock_guard<Lockable> lock(m);
|
||||
return func(
|
||||
boost::forward<Arg1>(arg1),
|
||||
boost::forward<Arg2>(arg2),
|
||||
boost::forward<Arg3>(arg3),
|
||||
boost::forward<Arg4>(arg4)
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_WITH_LOCK_GUARD_HPP
|
||||
|
||||
@@ -782,6 +782,14 @@ rule thread-compile ( sources : reqs * : name )
|
||||
;
|
||||
|
||||
|
||||
test-suite ts_with_lock_guard
|
||||
:
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp : with_lock_guard_simple_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp : with_lock_guard_bind_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp : with_lock_guard_move_p ]
|
||||
[ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp : with_lock_guard_lambda_p ]
|
||||
;
|
||||
|
||||
explicit ts_invoke ;
|
||||
test-suite ts_invoke
|
||||
:
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// (C) Copyright 2013 Ruslan Baratov
|
||||
// Copyright (C) 2014 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See www.boost.org/libs/thread for documentation.
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp> // BOOST_TEST
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/with_lock_guard.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
Foo(int value): value_(value) {
|
||||
}
|
||||
|
||||
int func(int a, int b) const {
|
||||
BOOST_TEST(a == 1);
|
||||
BOOST_TEST(b == 31);
|
||||
return a + b + value_;
|
||||
}
|
||||
|
||||
int func_ref(int& a) const {
|
||||
a = 133;
|
||||
return 36;
|
||||
}
|
||||
|
||||
void func_ref(int& a, int& b, int* c) const {
|
||||
BOOST_TEST(value_ == 3);
|
||||
a = 567;
|
||||
b = 897;
|
||||
*c = 345;
|
||||
}
|
||||
|
||||
private:
|
||||
int value_;
|
||||
};
|
||||
|
||||
void test_bind() {
|
||||
boost::mutex m;
|
||||
|
||||
Foo foo(2);
|
||||
|
||||
int res_bind = boost::with_lock_guard(
|
||||
m,
|
||||
boost::bind(&Foo::func, foo, 1, 31)
|
||||
);
|
||||
BOOST_TEST(res_bind == 34);
|
||||
|
||||
int a = 0;
|
||||
int res_bind_ref = boost::with_lock_guard(
|
||||
m,
|
||||
boost::bind(&Foo::func_ref, foo, boost::ref(a))
|
||||
);
|
||||
BOOST_TEST(res_bind_ref == 36);
|
||||
BOOST_TEST(a == 133);
|
||||
|
||||
a = 0;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
Foo boo(3);
|
||||
boost::with_lock_guard(
|
||||
m, boost::bind(&Foo::func_ref, boo, boost::ref(a), boost::ref(b), &c)
|
||||
);
|
||||
BOOST_TEST(a == 567);
|
||||
BOOST_TEST(b == 897);
|
||||
BOOST_TEST(c == 345);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
void test_bind_non_const() {
|
||||
std::cout << "c++11 variadic templates disabled" << std::endl;
|
||||
}
|
||||
#else
|
||||
|
||||
// calling non-const bind methods supported only with c++11 variadic templates
|
||||
class Boo {
|
||||
public:
|
||||
Boo(int value): value_(value) {
|
||||
}
|
||||
|
||||
int func(int a, int b) {
|
||||
BOOST_TEST(a == 7);
|
||||
BOOST_TEST(b == 3);
|
||||
return a - b + value_;
|
||||
}
|
||||
|
||||
int func_ref(int& a) {
|
||||
a = 598;
|
||||
return 23;
|
||||
}
|
||||
|
||||
void func_ref(int& a, int& b, int* c) {
|
||||
BOOST_TEST(value_ == 67);
|
||||
a = 111;
|
||||
b = 222;
|
||||
*c = 333;
|
||||
}
|
||||
|
||||
private:
|
||||
int value_;
|
||||
};
|
||||
|
||||
void test_bind_non_const() {
|
||||
boost::mutex m;
|
||||
|
||||
Boo boo(20);
|
||||
|
||||
int res_bind = boost::with_lock_guard(
|
||||
m,
|
||||
boost::bind(&Boo::func, boo, 7, 3)
|
||||
);
|
||||
BOOST_TEST(res_bind == 24);
|
||||
|
||||
int a = 0;
|
||||
int res_bind_ref = boost::with_lock_guard(
|
||||
m,
|
||||
boost::bind(&Boo::func_ref, boo, boost::ref(a))
|
||||
);
|
||||
BOOST_TEST(res_bind_ref == 23);
|
||||
BOOST_TEST(a == 598);
|
||||
|
||||
a = 0;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
Boo foo(67);
|
||||
boost::with_lock_guard(
|
||||
m, boost::bind(&Boo::func_ref, foo, boost::ref(a), boost::ref(b), &c)
|
||||
);
|
||||
BOOST_TEST(a == 111);
|
||||
BOOST_TEST(b == 222);
|
||||
BOOST_TEST(c == 333);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
test_bind();
|
||||
test_bind_non_const();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// (C) Copyright 2013 Ruslan Baratov
|
||||
// Copyright (C) 2014 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See www.boost.org/libs/thread for documentation.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE)
|
||||
# define BOOST_RESULT_OF_USE_DECLTYPE
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp> // BOOST_TEST
|
||||
|
||||
#include <iostream> // std::cout
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/with_lock_guard.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_LAMBDAS)
|
||||
void test_lambda() {
|
||||
std::cout << "C++11 lambda disabled" << std::endl;
|
||||
}
|
||||
#else
|
||||
void test_lambda() {
|
||||
boost::mutex m;
|
||||
int res_1 = boost::with_lock_guard(
|
||||
m,
|
||||
[](int a) {
|
||||
BOOST_TEST(a == 13);
|
||||
return a + 3;
|
||||
},
|
||||
13
|
||||
);
|
||||
BOOST_TEST(res_1 == 16);
|
||||
|
||||
int v = 0;
|
||||
int res_2 = boost::with_lock_guard(
|
||||
m,
|
||||
[&v](int a) {
|
||||
BOOST_TEST(a == 55);
|
||||
v = 15;
|
||||
return 45;
|
||||
},
|
||||
55
|
||||
);
|
||||
BOOST_TEST(res_2 == 45);
|
||||
BOOST_TEST(v == 15);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
std::cout << std::boolalpha;
|
||||
test_lambda();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// (C) Copyright 2013 Ruslan Baratov
|
||||
// Copyright (C) 2014 Vicente J. Botet Escriba
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See www.boost.org/libs/thread for documentation.
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp> // BOOST_TEST
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/with_lock_guard.hpp>
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
explicit Foo(int a) : a_(a) {
|
||||
}
|
||||
|
||||
Foo(BOOST_RV_REF(Foo) foo) : a_(foo.a_) {
|
||||
BOOST_ASSERT(&foo != this);
|
||||
foo.a_ = 0;
|
||||
}
|
||||
|
||||
Foo& operator=(BOOST_RV_REF(Foo) foo) {
|
||||
BOOST_ASSERT(&foo != this);
|
||||
a_ = foo.a_;
|
||||
foo.a_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int get() const {
|
||||
return a_;
|
||||
}
|
||||
|
||||
private:
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(Foo)
|
||||
|
||||
int a_;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
bool func_with_2_arg(BOOST_FWD_REF(T1) arg_1, BOOST_FWD_REF(T2) arg_2) {
|
||||
BOOST_TEST(arg_1.get() == 3);
|
||||
BOOST_TEST(arg_2.get() == 767);
|
||||
return false;
|
||||
}
|
||||
|
||||
void test_movable() {
|
||||
boost::mutex m;
|
||||
|
||||
Foo foo_1(3);
|
||||
Foo foo_2(767);
|
||||
|
||||
bool res = boost::with_lock_guard(
|
||||
m, &func_with_2_arg<Foo, Foo>, boost::move(foo_1), boost::move(foo_2)
|
||||
);
|
||||
BOOST_TEST(!res);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
void test_real_movable() {
|
||||
std::cout << "c++11 move emulated" << std::endl;
|
||||
}
|
||||
#else
|
||||
// test real one
|
||||
class Boo {
|
||||
public:
|
||||
Boo(int a) : a_(a) {
|
||||
}
|
||||
|
||||
Boo(Boo&& boo) : a_(boo.a_) {
|
||||
BOOST_ASSERT(&boo != this);
|
||||
boo.a_ = 0;
|
||||
}
|
||||
|
||||
int get() const {
|
||||
return a_;
|
||||
}
|
||||
|
||||
BOOST_DELETED_FUNCTION(Boo(Boo&))
|
||||
BOOST_DELETED_FUNCTION(Boo& operator=(Boo&))
|
||||
BOOST_DELETED_FUNCTION(Boo& operator=(Boo&&))
|
||||
private:
|
||||
int a_;
|
||||
};
|
||||
|
||||
void func_with_3_arg(Boo&& boo_1, Boo&& boo_2, Boo&& boo_3) {
|
||||
BOOST_TEST(boo_1.get() == 11);
|
||||
BOOST_TEST(boo_2.get() == 12);
|
||||
BOOST_TEST(boo_3.get() == 13);
|
||||
}
|
||||
|
||||
void test_real_movable() {
|
||||
boost::mutex m;
|
||||
|
||||
Boo boo_3(13);
|
||||
|
||||
boost::with_lock_guard(
|
||||
m, func_with_3_arg, Boo(11), Boo(12), boost::move(boo_3)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
test_movable();
|
||||
test_real_movable();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// (C) Copyright 2013 Ruslan Baratov
|
||||
// (C) Copyright 2013 Ruslan Baratov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See www.boost.org/libs/thread for documentation.
|
||||
|
||||
#define BOOST_THREAD_VERSION 4
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp> // BOOST_TEST
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/with_lock_guard.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
void func_with_0_arg() {
|
||||
}
|
||||
|
||||
void func_with_1_arg(int arg_1) {
|
||||
BOOST_TEST(arg_1 == 3);
|
||||
}
|
||||
|
||||
bool func_with_2_arg(int arg_1, bool arg_2) {
|
||||
BOOST_TEST(arg_1 == 3);
|
||||
BOOST_TEST(arg_2 == true);
|
||||
return !arg_2;
|
||||
}
|
||||
|
||||
int func_with_3_arg(int arg_1, bool arg_2, const char* arg_3) {
|
||||
BOOST_TEST(arg_1 == 13);
|
||||
BOOST_TEST(arg_2 == false);
|
||||
BOOST_TEST(std::string(arg_3) == "message for func with 3 arg");
|
||||
return 12;
|
||||
}
|
||||
|
||||
const char* func_with_4_arg(int arg_1, bool arg_2, int* arg_3, int& arg_4) {
|
||||
BOOST_TEST(arg_1 == 23);
|
||||
BOOST_TEST(arg_2 == false);
|
||||
*arg_3 = 128;
|
||||
arg_4 = 456;
|
||||
return "hello";
|
||||
}
|
||||
|
||||
void test_simple() {
|
||||
boost::mutex m;
|
||||
|
||||
// #0
|
||||
boost::with_lock_guard(m, func_with_0_arg);
|
||||
|
||||
// #1
|
||||
boost::with_lock_guard(m, func_with_1_arg, 3);
|
||||
|
||||
// #2
|
||||
bool res2 = boost::with_lock_guard(m, func_with_2_arg, 3, true);
|
||||
BOOST_TEST(res2 == false);
|
||||
|
||||
// #3
|
||||
int arg1 = 13;
|
||||
const char* mes = "message for func with 3 arg";
|
||||
int res3 = boost::with_lock_guard(m, func_with_3_arg, arg1, false, mes);
|
||||
BOOST_TEST(res3 == 12);
|
||||
|
||||
// #4
|
||||
int arg3 = 0;
|
||||
int arg4 = 0;
|
||||
const char* res4 = boost::with_lock_guard(
|
||||
m,
|
||||
func_with_4_arg,
|
||||
23,
|
||||
false,
|
||||
&arg3,
|
||||
boost::ref(arg4)
|
||||
);
|
||||
BOOST_TEST(arg3 == 128);
|
||||
BOOST_TEST(arg4 == 456);
|
||||
BOOST_TEST(std::string(res4) == "hello");
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
void test_variadic_templates() {
|
||||
std::cout << "C++11 variadic templates disabled" << std::endl;
|
||||
}
|
||||
#else
|
||||
int func_with_5_args(int a1, char a2, int& a3, bool* a4, bool a5) {
|
||||
BOOST_TEST(a1 == 12);
|
||||
BOOST_TEST(a2 == 'x');
|
||||
BOOST_TEST(a5 == false);
|
||||
a3 = 135;
|
||||
*a4 = false;
|
||||
return 45;
|
||||
}
|
||||
|
||||
int func_with_6_args(int a1, char a2, int& a3, bool* a4, int&& a5, bool a6) {
|
||||
BOOST_TEST(a1 == 12);
|
||||
BOOST_TEST(a2 == 'N');
|
||||
BOOST_TEST(a5 == 2 || a5 == 13);
|
||||
BOOST_TEST(a6 == false);
|
||||
a3 = 200;
|
||||
*a4 = true;
|
||||
return 888;
|
||||
}
|
||||
|
||||
void test_variadic_templates() {
|
||||
boost::mutex m;
|
||||
|
||||
int a3 = 0;
|
||||
bool a4 = true;
|
||||
int res5 = boost::with_lock_guard(
|
||||
m, func_with_5_args, 12, 'x', a3, &a4, false
|
||||
);
|
||||
BOOST_TEST(a3 == 135);
|
||||
BOOST_TEST(a4 == false);
|
||||
BOOST_TEST(res5 == 45);
|
||||
|
||||
int res6 = boost::with_lock_guard(
|
||||
m, func_with_6_args, 12, 'N', a3, &a4, 2, false
|
||||
);
|
||||
BOOST_TEST(a3 == 200);
|
||||
BOOST_TEST(a4 == true);
|
||||
BOOST_TEST(res6 == 888);
|
||||
|
||||
a3 = 0;
|
||||
a4 = false;
|
||||
int a5 = 13;
|
||||
int res6_move = boost::with_lock_guard(
|
||||
m, func_with_6_args, 12, 'N', a3, &a4, boost::move(a5), false
|
||||
);
|
||||
BOOST_TEST(a3 == 200);
|
||||
BOOST_TEST(a4 == true);
|
||||
BOOST_TEST(res6 == 888);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
test_simple();
|
||||
test_variadic_templates();
|
||||
return boost::report_errors();
|
||||
}
|
||||
Reference in New Issue
Block a user