EDIT : The call to std::bind() can be replaced with something else, I just want runAsyncTerminateOnException() to work with the same signature than std::async(), like just a wrapper to it
I am trying to create a wrapper to std::async().
Do you know how to make the wrapper working as well when a direct call to std::async() works ?
Note : I will not modify the print() function signature, this is an example. I would like the wrapper to be generic and to work for every possible parameters that are well handled by a direct call to std::async().
Thank you.
http://ideone.com/HbBqeo
#include <iostream>
#include <functional>
#include <future>
template<class Fn, class... Args>
inline auto runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
auto make_call = std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...);
return std::async(std::launch::async, [=]() -> decltype(make_call()) {
try {
return make_call();
} catch (...) {
std::cout << "Terminate Called!" << std::endl;
std::terminate();
}
});
}
struct Foo {
template<class... Args>
void print(Args&&... args) {
printf("Foo::print(%d)\n", std::forward<Args>(args)...);
}
};
int main() {
Foo foo;
std::future<void> future = std::async(std::launch::async, &Foo::print<int>, &foo, 2);
std::future<void> future2 = runAsyncTerminateOnException(&Foo::print<int>, &foo, 2);
// your code goes here
return 0;
}
You need to change your runAsyncTerminateOnException call as follows:
std::future<void> future2 =
runAsyncTerminateOnException(&Foo::print<const int&>, &foo, 2);
This is due to an unfortunate interaction between std::bind, variadic templates and perfect forwarding.
I suggest you to use lambdas instead, which are almost always superior to std::bind. (For more information, see this talk from STL.)
template<class Fn>
inline auto runAsyncTerminateOnException(Fn&& fn)
{
return std::async(std::launch::async, [=]() -> decltype(fn()) {
try {
return fn();
} catch (...) {
std::cout << "Terminate Called!" << std::endl;
std::terminate();
}
});
}
(Note that I'm copying fn into the lambda - if you want a more correct and generic solution, you should consider perfect-forward capturing the object into the lambda.)
std::future<void> future2 =
runAsyncTerminateOnException([&foo]{ return foo.print(2); });
wandbox example
I found the solution for c++17.
It works only if we do not use auto for the return type of runTerminateOnException().
template<class Fn, class... Args>
inline std::result_of_t<Fn&&(Args&&...)> runTerminateOnException(Fn&& fn, Args&&... args) {
try {
return std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...);
} catch (...) {
std::terminate();
}
}
template<class Fn, class... Args>
inline auto runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
return std::async(std::launch::async, runTerminateOnException<Fn, Args&&...>, std::forward<Fn>(fn), std::forward<Args>(args)...);
}
Related
I want to implement something like Java's TimerTask in C++. I want to use it for invoking functions sometimes, not periodic. For periodic launching it will be a good idea to implement "event loop" scheme with 2 threads, with creating tasks in the first thread and process it in the second. But I do not want to write much code. So I've written smth like this:
template <typename F, typename... Args>
auto timed_run(const uint64_t delay_ms, const F& function, Args... args) {
const auto f = [&] {
std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
function(args...);
};
auto future = std::async(std::launch::async, f);
return future;
}
But it does not work as I need because it is not asynchronous at all due to it waits at future destructor as described there.
So we need to create thread by ourselves. Okay, lets do it:
template <typename F, typename... Args>
auto timed_run(const uint64_t delay_ms, const F& function, Args... args) {
std::packaged_task<void()> task([&]() {
std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
function(args...);
});
auto future = task.get_future();
std::thread thread(std::move(task));
thread.detach();
return future;
}
In this implementation the are no locks and waits, but it simply does not run our function. It is because we can't use sleep on the detached threads.
So, how can I implement what i want?
You can have your timed_run function launch an async task and return a future. At the callee point, just wait for the async task to complete.
[Demo]
#include <chrono>
#include <cstdint> // uint64_t
#include <fmt/core.h>
#include <future> // async
#include <thread> // this_thread
template <typename F, typename... Args>
auto timed_run(const std::uint64_t delay_ms, F&& f, Args&&... args) {
return std::async(std::launch::async, [=](){
std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
f(args...);
});
}
int main() {
using namespace std::chrono_literals;
auto print_dots = []() {
for (int i{4}; i > 0; --i) {
fmt::print(".\n");
std::this_thread::sleep_for(10ms);
}
};
auto print_square = [](int n) { fmt::print("{}\n", n*n); };
auto f1{ timed_run(0, print_dots) };
auto f2{ timed_run(20, print_square, 2) };
f1.get();
f2.get();
}
// Outputs something like:
//
// ..4..
template <typename F, typename... Args>
auto timed_run(const uint64_t delay_ms, F&& function, Args&&... args) {
std::packaged_task<void()> task([=]() {
std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
function(args...);
});
auto future = task.get_future();
std::thread(std::move(task)).detach();
return future;
}
Based on my previous question here Variadic template, function as argument
I have ended up with a simple class below, however how do I use std::invoke or some other method to call Tester::test with Tester::simple as argument? The examples provided at http://en.cppreference.com/w/cpp/utility/functional/invoke#Example were not very helpful for me and I tried many different ways of using std::invoke.
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
int main()
{
Tester t;
std::cout << t.test(t.simple, 3); // how do you modify this line such that the code compiles?
}
Thanks!
One way is to modify the definition of your test() member function like so:
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
We can then pass a member function pointer to test(), with the instance on which the method should be called as the second argument, and then the function arguments themselves:
int main()
{
Tester t;
std::cout << t.test(&Tester::simple, t, 3);
}
The reason this works is because std::invoke has a special overload for pointers-to-members, such that
std::invoke(ptr-to-member, instance, args...);
is called as
(instance.*ptr-to-member)(args...);
which is exactly what we want in this case.
Note, that std::invoke is a part of C++ 17. In case if it is not available, one might implement test function so that it accepts a pointer-to-member-function and an instance of a class:
template<typename F, typename T, typename... Args>
decltype(auto) test(F f, T&& t, Args&&... args) {
return (std::forward<T>(t).*f)(std::forward<Args>(args)...);
}
Now test accepts a pointer-to-member-function as a first argument, an instance of a class as a second argument and an arbitrary number of additional arguments.
Then test might be called like:
Tester t;
std::cout << t.test(&Tester::simple, t, 42);
WANDBOX EXAMPLE
Just to mention yet another possibility, you could wrap the member function call in a lambda and capture the instance t. In C++14 we can use the generic lambda for that, so we don't have to specify the parameters explicitly.
#include <iostream>
#include <utility>
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
int main()
{
Tester t;
std::cout << t.test([&t] (auto&&... args) { return t.simple(std::forward<decltype(args)>(args)...); }, 3);
}
In relation to a previous question (Is it possible to return an object of type T by reference from a lambda without using trailing return type syntax?), I was wondering if there is any other significant case or example in which trailing-return-type syntax, when using lambdas, can not be avoided.
In C++14, a bit contrived example is the use of sfinae in combination with a generic lambda:
[](auto &&arg)
-> decltype(arg.f(), void())
{ /* do whatever you want */ }
Anyway one could argue that a static_assert suffices:
[](auto &&arg) {
static_assert(has_metod_f<std::decay_t<decltype(arg)>>::value, "!");
/* do whatever you want */
}
Where has_method_f is the common detector idiom.
Anyway, imagine a case where you want to construct a composed functor starting from a bunch of lambdas:
#include<utility>
#include<iostream>
template<typename...>
struct Base;
template<typename Func, typename... Others>
struct Base<Func, Others...>: Func, Base<Others...> {
Base(Func func, Others... others)
: Func{std::move(func)}, Base<Others...>{std::move(others)...}
{}
template<typename... Args>
auto operator()(int, Args&&... args)
-> decltype(Func::operator()(std::forward<Args>(args)...)) {
Func::operator()(std::forward<Args>(args)...);
}
template<typename... Args>
auto operator()(char, Args&&... args) {
Base<Others...>::operator()(0, std::forward<Args>(args)...);
}
};
template<>
struct Base<> {
template<typename... Args>
auto operator()(Args&&...) {
std::cout << "fallback" << std::endl;
}
};
template<typename... Ops>
struct Mixin: Base<Ops...> {
Mixin(Ops... ops)
: Base<Ops...>{std::move(ops)...}
{}
template<typename... Args>
auto operator()(Args&&... args) {
return Base<Ops...>::operator()(0, std::forward<Args>(args)...);
}
};
struct T { void f() {} };
struct U {};
int main() {
auto l1 = [](auto &&arg) -> decltype(arg.f(), void()) {
std::cout << "accept T" << std::endl;
};
auto l2 = [](U) {
std::cout << "accept U" << std::endl;
};
Mixin<decltype(l1), decltype(l2)> mixin{std::move(l1), std::move(l2)};
mixin(T{});
mixin(U{});
mixin(0);
}
In this case, a static_assert would prevent the compilation and it is not the expected result.
On the other side, the trailing return type can be used to enable sfinae directly on the lambdas with the help of their wrappers.
I suppose that another case is when there is type inconsistency between differents returns.
A silly example
std::function<long(int)> f
= [](int v) -> long { if ( v ) return v; else return 0L; };
Obviously you can avoid it if you avoid inconsistency so I don't know if it's significant.
So I wrote a function that composes "sequentially" void lambdas so that I can use them at once in an algorithm:
template <typename F, typename... Fs>
auto lambdaList(F f, Fs... fs)
{
return [=] (auto&... args) { f(args...); lambdaList(fs...)(args...); };
}
template <typename F>
auto lambdaList(F f)
{
return [=] (auto&... args) { f(args...); };
}
It works if I use local lambdas, but not when I use functions in a different namespace:
#include <iostream>
namespace foo {
void a() { std::cout << "a\n"; }
void b() { std::cout << "b\n"; }
}
template <typename F, typename... Fs>
auto lambdaList(F f, Fs... fs)
{
return [=] (auto&... args) { f(args...); lambdaList(fs...)(args...); };
}
template <typename F>
auto lambdaList(F f)
{
return [=] (auto&... args) { f(args...); };
}
int main() {
auto printStarBefore = [] (const std::string& str) {
std::cout << "* " + str;
};
auto printStarAfter = [] (const std::string& str) {
std::cout << str + " *" << std::endl;
};
lambdaList(printStarBefore, printStarAfter)("hi"); // ok
lambdaList(foo::a, foo::b)(); // error
}
The error is no matching function for call to 'lambdaList()' with:
main.cpp:11:56: note: candidate expects at least 1 argument, 0 provided
return [=] (auto&... args) { f(args...); lambdaList(fs...)(args...); };
~~~~~~~~~~^~~~~~~
Why does it sometimes work but sometimes not?
You need to invert your functions:
template <typename F>
auto lambdaList(F f)
{
return [=] (auto&... args) { f(args...); };
}
template <typename F, typename... Fs>
auto lambdaList(F f, Fs... fs)
{
return [=] (auto&... args) { f(args...); lambdaList(fs...)(args...); };
}
As-is, your base case won't be found by unqualified lookup in your recursive case - it can only be found by argument dependent lookup. If the arguments aren't in the same namespace as lambdaList, then it won't be found at all and the recursive step will always call itself. That's the source of your error.
The new ordering allows the base-case lambdaList() to be found by normal unqualified lookup - now it's visible at the point of definition of the recursive lambdaList().
That said, we can do better. Write one function that invokes everything:
template <typename... Fs>
auto lambdaList(Fs... fs) {
using swallow = int [];
return [=](auto const&... args) {
(void)swallow{0,
(void(fs(args...)), 0)...
};
};
}
And now we don't need to worry about any kind of lookup. If you have access to a modern-enough compiler that supports some C++1z features, the above can be greatly reduced with:
template <typename... Fs>
auto lambdaList(Fs... fs) {
return [=](auto const&... args) {
(fs(args...), ...);
};
}
That's downright understandable!
I want to name a thread, but unfortunately the pthread_setname_np() on Mac works only inside current thread.
Then I do the wrapper around std::thread with a following constructor:
template <class F, class ... Args>
Thread::Thread(const char* name, F&& f, Args&&... args) {
thread_ = std::thread([name, f, args...]() {
pthread_setname_np(name);
f(args...);
});
}
But it doesn't work with class methods:
error: called object type '<complex type>' is not a function or function pointer
f(args...);
^
In the code like this:
threads_.emplace_back("Name", &Aggregator<T>::DoPop, this, some_arg);
What is a proper way to wrap the std::thread and set the thread name, preserving the whole interface excepting the name argument in the constructor?
You can use std::mem_fn to call a member function. The first argument in args has to be the pointer to the member object.
Example:
#include <thread>
#include <functional>
template <class F, class ... Args>
std::thread thread_factory(const char* name, F&& f, Args&&... args) {
return std::thread([=]{
pthread_setname_np(name);
auto fun = std::mem_fn(f);
fun(args...);
});
}
struct test {
int t(int val) {
return val;
}
};
int main() {
test t;
auto b = thread_factory("name", &test::t, &t, 5);
b.join();
}
you have to bind your member function to a class instance. here's your function presented slightly differently with a (working) test:
#include <iostream>
#include <thread>
template <class F, class ... Args>
std::thread launch_named_thread(const char* name, F&& f, Args&&... args) {
return std::thread([name, f, args...]() {
pthread_setname_np(name);
f(args...);
});
}
struct myclass
{
void thread_loop(int i)
{
std::cout << i << std::endl;
}
};
auto main() -> int
{
myclass x;
auto t = launch_named_thread("hello", std::bind(&myclass::thread_loop, &x, 6));
// this could be:
// auto t = launch_named_thread("hello", std::bind(&myclass::thread_loop, &x, std::placeholders::_1), 6);
// the difference is subtle. i'll leave it to you to work out why
t.join();
return 0;
}