How to run function after delay asynchronously in C++ - c++

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;
}

Related

emplace lambda task that used packaged_task into a queue

So I have this enqueue implementation for a threadpool
template <typename F, typename... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
using return_type = decltype(f(args...));
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
auto result = task->get_future();
{
std::unique_lock<std::mutex> lock(m_queue_mutex);
if (m_stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
m_tasks.emplace([task]() { (*task)(); });
}
m_condition.notify_one();
return result;
}
So far so good, but I would like to avoid using memory allocation and not use the make_shared.
So I change it to this:
template <typename F, typename... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
using return_type = decltype(f(args...));
auto task = std::packaged_task<return_type()>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
auto result = task.get_future();
{
std::unique_lock<std::mutex> lock(m_queue_mutex);
if (m_stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
m_tasks.emplace([task = std::move(task)]() mutable { task(); });
}
m_condition.notify_one();
return result;
}
As far as I know, there is no copy here.
the task should be moved into the lambda and the lambda should be moved into the queue but still, I get this error:
use of deleted function ‘std::packaged_task<_Res(_ArgTypes
...)>::packaged_task(const std::packaged_task<_Res(_ArgTypes ...)>&)
[with _Res = void; _ArgTypes = {}]’ 38 |
m_tasks.emplace(task mutable { task(); });
what I understand is that I'm trying to copy the packaged_task and its copy constructor is deleted.
here you can play with the full code
https://godbolt.org/z/bEsPfabz6
thanks!

Subclassing std::thread: problems with variadic template functions in constuctor

I'm trying to subclass std::thread such that a member function of the subclass is executed on the new thread before the caller's passed-in function. Something like the following invalid code:
#include <thread>
#include <utility>
class MyThread : public std::thread {
template<class Func, class... Args>
void start(Func&& func, Args&&... args) {
... // Useful, thread-specific action
func(args...);
}
public:
template<class Func, class... Args>
MyThread(Func&& func, Args&&... args)
: std::thread{[=]{start(std::forward<Func>(func),
std::forward<Args>(args)...);}} {
}
};
g++ -std=c++11 has the following issue with the above code:
MyThread.h: In lambda function:
MyThread.h:ii:jj: error: parameter packs not expanded with '...':
std::forward<Args>(args)...);}}
^
I've tried a dozen different variations in the initializer-list to no avail.
How can I do what I want?
The biggest difficulty I had when I did this before was getting all the behavior of std::thread. It's constructor can take not only a pointer to a free function, but also a class method pointer and then a object of the class as the first argument. There are a number of variations on that: class methods, class function object data members, an object of the class type vs a pointer to an object, etc.
This is for C++14:
class MyThread : public std::thread {
void prolog() const { std::cout << "prolog\n"; }
public:
template <typename... ArgTypes>
MyThread(ArgTypes&&... args) :
std::thread(
[this, bfunc = std::bind(std::forward<ArgTypes>(args)...)]
() mutable {
prolog();
bfunc();
})
{ }
};
If you put the prolog code inside the lambda and it doesn't call class methods, then the capture of this is not needed.
For C++11, a small change is needed because of the lack of capture initializers, so the bind must be passed as an argument to std::thread:
std::thread(
[this]
(decltype(std::bind(std::forward<ArgTypes>(args)...))&& bfunc) mutable {
prolog();
bfunc();
}, std::bind(std::forward<ArgTypes>(args)...))
Here's a test program that also exercises the class member form of std::thread:
int main()
{
auto x = MyThread([](){ std::cout << "lambda\n"; });
x.join();
struct mystruct {
void func() { std::cout << "mystruct::func\n"; }
} obj;
auto y = MyThread(&mystruct::func, &obj);
y.join();
return 0;
}
I haven't checked, but I'm a bit worried that the capture of this, also seen in other solutions, is not safe in some cases. Consider when the object is an rvalue that is moved, as in std::thread t = MyThread(args). I think the MyThread object will go away before the thread it has created is necessarily finished using it. The "thread" will be moved into a new object and still be running, but the captured this pointer will point to a now stale object.
I think you need to insure your constructor does not return until your new thread is finished using all references or pointers to the class or class members. Capture by value, when possible, would help. Or perhaps prolog() could be a static class method.
This should do it (c++11 and c++14 solutions provided):
C++14
#include <thread>
#include <utility>
#include <tuple>
class MyThread : public std::thread {
template<class Func, class ArgTuple, std::size_t...Is>
void start(Func&& func, ArgTuple&& args, std::index_sequence<Is...>) {
// Useful, thread-specific action
func(std::get<Is>(std::forward<ArgTuple>(args))...);
}
public:
template<class Func, class... Args>
MyThread(Func&& func, Args&&... args)
: std::thread
{
[this,
func = std::forward<Func>(func),
args = std::make_tuple(std::forward<Args>(args)...)] () mutable
{
using tuple_type = std::decay_t<decltype(args)>;
constexpr auto size = std::tuple_size<tuple_type>::value;
this->start(func, std::move(args), std::make_index_sequence<size>());
}
}
{
}
};
int main()
{
auto x = MyThread([]{});
}
In C++17 it's trivial:
#include <thread>
#include <utility>
#include <tuple>
#include <iostream>
class MyThread : public std::thread {
public:
template<class Func, class... Args>
MyThread(Func&& func, Args&&... args)
: std::thread
{
[this,
func = std::forward<Func>(func),
args = std::make_tuple(std::forward<Args>(args)...)] () mutable
{
std::cout << "execute prolog here" << std::endl;
std::apply(func, std::move(args));
std::cout << "execute epilogue here" << std::endl;
}
}
{
}
};
int main()
{
auto x = MyThread([](int i){
std::cout << i << std::endl;
}, 6);
x.join();
}
C++11 (we have to facilitate moving objects into the mutable lambda, and provide the missing std::index_sequence):
#include <thread>
#include <utility>
#include <tuple>
namespace notstd
{
using namespace std;
template<class T, T... Ints> struct integer_sequence
{};
template<class S> struct next_integer_sequence;
template<class T, T... Ints> struct next_integer_sequence<integer_sequence<T, Ints...>>
{
using type = integer_sequence<T, Ints..., sizeof...(Ints)>;
};
template<class T, T I, T N> struct make_int_seq_impl;
template<class T, T N>
using make_integer_sequence = typename make_int_seq_impl<T, 0, N>::type;
template<class T, T I, T N> struct make_int_seq_impl
{
using type = typename next_integer_sequence<
typename make_int_seq_impl<T, I+1, N>::type>::type;
};
template<class T, T N> struct make_int_seq_impl<T, N, N>
{
using type = integer_sequence<T>;
};
template<std::size_t... Ints>
using index_sequence = integer_sequence<std::size_t, Ints...>;
template<std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
}
template<class T>
struct mover
{
mover(T const& value) : value_(value) {}
mover(T&& value) : value_(std::move(value)) {}
mover(const mover& other) : value_(std::move(other.value_)) {}
T& get () & { return value_; }
T&& get () && { return std::move(value_); }
mutable T value_;
};
class MyThread : public std::thread {
template<class Func, class ArgTuple, std::size_t...Is>
void start(Func&& func, ArgTuple&& args, notstd::index_sequence<Is...>) {
// Useful, thread-specific action
func(std::get<Is>(std::forward<ArgTuple>(args))...);
}
public:
template<class Func, class... Args>
MyThread(Func&& func, Args&&... args)
: std::thread()
{
using func_type = typename std::decay<decltype(func)>::type;
auto mfunc = mover<func_type>(std::forward<Func>(func));
using arg_type = decltype(std::make_tuple(std::forward<Args>(args)...));
auto margs = mover<arg_type>(std::make_tuple(std::forward<Args>(args)...));
static_cast<std::thread&>(*this) = std::thread([this, mfunc, margs]() mutable
{
using tuple_type = typename std::remove_reference<decltype(margs.get())>::type;
constexpr auto size = std::tuple_size<tuple_type>::value;
this->start(mfunc.get(), std::move(margs).get(), notstd::make_index_sequence<size>());
});
}
};
int main()
{
auto x = MyThread([](int i){}, 6);
x.join();
}

Wrapper to std::async() not working

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)...);
}

How to name std::thread on Mac OS X in C++11?

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;
}

A timer for arbitrary functions

I tried to build a function template that can measure the execution time of functions of arbitrary type. Here is what I've tried so far:
#include <chrono>
#include <iostream>
#include <type_traits>
#include <utility>
// Executes fn with arguments args and returns the time needed
// and the result of f if it is not void
template <class Fn, class... Args>
auto timer(Fn fn, Args... args)
-> std::pair<double, decltype(fn(args...))> {
static_assert(!std::is_void<decltype(fn(args...))>::value,
"Call timer_void if return type is void!");
auto start = std::chrono::high_resolution_clock::now();
auto ret = fn(args...);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
return { elapsed_seconds.count(), ret };
}
// If fn returns void, only the time is returned
template <class Fn, class... Args>
double timer_void(Fn fn, Args... args) {
static_assert(std::is_void<decltype(fn(args...))>::value,
"Call timer for non void return type");
auto start = std::chrono::high_resolution_clock::now();
fn(args...);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
return elapsed_seconds.count();
}
int main () {
//This call is ambigous if the templates have the same name
std::cout << timer([](double a, double b){return a*b;},1,2).first;
}
Notice that I have to have a function with a different name for void(...) functions. Is there any way to get rid of the second function?
(And is what I did correct in the first place?)
You can use enable_if or tag dispatching. Enable_if seems to be the quicker way in this case:
#include <type_traits>
template <class Fn, class... Args>
auto timer(Fn fn, Args && ... args) -> typename std::enable_if<
// First template argument is the enable condition
!std::is_same<
decltype( fn( std::forward<Args>(args) ... )),
void >::value,
// Second argument is the actual return type
std::pair<double, decltype(fn(std::forward<Args>(args)...))> >::type
{
// Implementation for the non-void case
}
template <class Fn, class... Args>
auto timer(Fn fn, Args &&... args) -> typename std::enable_if<
std::is_same<
decltype( fn( std::forward<Args>(args) ... )),
void >::value,
double>::type
{
// Implementation for void case
}
Also you should use perfect forwarding to pass the arguments to the called function:
auto timer(Fn fn, Args && ... args) // ...
~~~^
And when you call the function:
auto ret = fn( std::forward<Args>(args)...);
Demo. Notice that this works with functions, lambda and callable objects; pretty much everything with an operator().
From a design standpoint, I see no problem in returning a std::pair. Since C++11 has std::tie, returning a pair/ tuple is the legitimate way of returning multiple results from a function. I would go forward and say that for consistency in the void case you should return a tuple with only one element.
In this case I would pass the duration as a reference to the the wrapper of the function call:
#include <chrono>
#include <iostream>
#include <thread>
template <typename Duration, class Fn, class... Args>
auto call(Duration& duration, Fn fn, Args... args) -> decltype(fn(args...)) {
using namespace std::chrono;
struct DurationGuard {
Duration& duration;
high_resolution_clock::time_point start;
DurationGuard(Duration& duration)
: duration(duration),
start(high_resolution_clock::now())
{}
~DurationGuard() {
high_resolution_clock::time_point end = high_resolution_clock::now();
duration = duration_cast<Duration>(end - start);
}
};
DurationGuard guard(duration);
return fn(args...);
}
void f() {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int g() {
std::this_thread::sleep_for(std::chrono::seconds(1));
return 42;
}
int main () {
using namespace std::chrono;
duration<double> s;
call(s, f);
std::cout << s.count() << '\n';
milliseconds ms;
int n = call(ms, g);
std::cout << ms.count() << ", " << n << '\n';
}
You may wrap it up in a class:
#include <chrono>
#include <iostream>
#include <thread>
template <typename Duration = std::chrono::duration<double>>
class InvokeDuration
{
public:
template<typename Fn, class... Args>
auto operator () (Fn fn, Args... args) -> decltype(fn(args...)) {
using namespace std::chrono;
struct Guard {
Duration& duration;
high_resolution_clock::time_point start;
Guard(Duration& duration)
: duration(duration),
start(high_resolution_clock::now())
{}
~Guard() {
high_resolution_clock::time_point end = high_resolution_clock::now();
duration = duration_cast<Duration>(end - start);
}
};
Guard guard(m_duration);
return fn(args...);
}
const Duration& duration() const { return m_duration; }
typename Duration::rep count() const { return m_duration.count(); }
private:
Duration m_duration;
};
void f() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int g(int n) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return n;
}
int main () {
InvokeDuration<> invoke;
invoke(f);
std::cout << invoke.count() << '\n';
int n = invoke(g, 42);
std::cout << invoke.count() << ", " << n << '\n';
}
Note: Returning void from a function call is well defined: void a() { return b(); } with void b()
Just overload it. Also, you should change the function signature as below. Live code.
template <typename R, typename... Args>
auto timer(R (*fn)(Args...), Args... args) -> std::pair<double, R>
{
//...
auto ret = fn(args...);
//...
return { elapsed_seconds.count(), ret };
}
And for void:
template <typename... Args>
auto timer(void (*fn)(Args...), Args... args) -> double
{
//...
fn(args...);
//...
return elapsed_seconds.count();
}
However it doesn't work for lambdas.
There is a workaround for non-capturing lambda functions (which brakes the generalization).
template <typename Function>
struct function_traits
: public function_traits<decltype(&Function::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
typedef ReturnType (*pointer)(Args...);
typedef std::function<ReturnType(Args...)> function;
};
template <typename Function>
typename function_traits<Function>::pointer
to_function_pointer (const Function& lambda)
{
return static_cast<typename function_traits<Function>::pointer>(lambda);
}
and then you can pass lambdas like this:
timer(to_function_pointer([](){
// Lambda function
}));
C++14 generic lambdas remove the need to use templates. A code snippet I saw in Effective Modern C++ demonstrates this :
auto timeFuncInvocation =
[](auto&& func, auto&&... params)
{
start timer;
std::forward<decltype(func)>(func)(
std::forward<decltype(params)>(params)...);
stop timer and record elapsed time;
};