Pass QTimer::singleShot to std::async using std::bind - c++

The following code starts a non-blocking timer that will launch the function myFunc after one second:
MyClass.h:
std::future<void> timer_future_;
MyClass.cpp:
timer_future_ = std::async(
std::launch::async,
[this] { QTimer::singleShot(1000,
[this] {this->myFunc();}
);
}
);
I would like to replace the lambda functions with std::functions. I have successfully replaced the second lambda as follows:
timer_future_ = std::async(
std::launch::async,
[this] { QTimer::singleShot(1000,
std::bind(&MyClass::myFunc, this)
);
}
);
How can I now replace the first lambda with another std::bind() call?
Note that the function QTimer::singleShot is from the Qt libraries; its documentation is here. Its prototype is:
void QTimer::singleShot(int msec, Functor functor)
As per this question, the definition of the Functor type can be found in QObject.h. It says:
template <class FunctorT, class R, typename... Args> class Functor { /*...*/ }
After some research, I understand that the std::bind() that will replace the first lambda must take account of the following:
QTimer::singleShot is an overloaded function, so I must use a cast to disambiguate the call to it
QTimer::singleShot is a static member function, so the pointer to it must resemble a pointer to a non-member function
I have made several unsuccessful attempts, the last of which was:
timer_future_ = std::async(
std::launch::async,
std::bind( ( void(*) (int, Functor<const std::function<void(void)>,void>) )&QTimer::singleShot,
1000,
std::bind(&MyClass::myFunc, this)
)
);
For this code, the MSVC compiler returned the error message
error: C2059: syntax error: ')'
on the third line.
Why don’t I just use the lambdas which are already working? The answer is simply that trying to use std::bind() instead is teaching me more about the various features of the C++ language and how to use them.
EDIT: Code that implements Kuba Ober's answer:
QTimer::singleShot(1000, [this] {
timer_future_ = std::async(
std::launch::async,
std::bind(&MyClass::myFunc, this)
);
});

The timer requires an event loop, and std::async will invoke it in a worker thread that doesn't have a running event loop. I question why would you ever want to do it?
If you want to run something in a worker thread after a delay, run the timer in a thread that has an event loop, and fire off the async action from that timer.

Count opening and closing brackets and add a semicolon

Related

How to process instances of classes in parallel in C++?

I have a variable number of instances of one class, normally 3. I would like to call the class functions in each iteration of an infinite loop. Currently it is working sequentially, meaning I call each member function after each other. I would like to parallelize that part. What do you recommend?
I tried to construct an std::vector<std::thread>. I could initialize the threads and call a function on them at initialization.
MyCustomClass my_class_instance();
std::thread one_thread(&MyCustomClass::init, &my_class_instance, "string");
threads_.push_back(std::move(one_thread));
But now I would like to get each thread of the vector threads and then to call the class member function. If it would be a std::vector of class instances I would just call: vector.at(index).class_function(). How do I do that for threads? Or is that not possible?
By the way, it is in C++.
Thanks
In c++11, speciy std::launch::async is one of your choice, if asynchronicity is essential for you.
There are two launch policy:
std::launch::async, means that the function must be run asynchronously, i.e, on a different thread.
std::launch::deferred, means that the function may run only when get or wait is called on the future return by std::async. When get or wait is invoked, the function will execute synchronously. The caller of the function will be blocks until the fucntion finish running. If get or wait
is not invoked, then the function will never run.
auto future1 = std::async(my_function); // run my_function using defautl launch policy
auto future2 = std::async(std::launch::async | std::launch::deferred) // run my_function either async or defered
Refered from the book "Effective Modern C++" by Scoot Meyers, item 36: Specify std::launch ::async if asynchronicity is essential.
If parallel computing is what you need, you may consider using OpenMP.
Reference: https://en.cppreference.com/w/cpp/thread/async
This code maybe help you.
class test_thread_instanse
{
public:
void operator()(int x)
{
std::cout << "test" <<x << std::endl;
}
};
int main()
{
std::thread t1(test_thread_instanse(), 1);
std::thread t2(test_thread_instanse(), 2);
std::thread t3(test_thread_instanse(), 3);
t1.join();
t2.join();
t3.join();
return(0);
}

C++ Multi-threading giving a templated std::bind to another thread

I try to give a std::bind to another existing thread currently waiting in a condition_variable. I really want to keep this other thread alive and not creating another one.
But I don't know how to give this std::bind to the other thread, due to the fact that everything is decided at compile-time.
I know that boost thread pool manage that, and I really wonder how and I'd like doing it without boost.
Here is some pseudo-code
class Exec
{
template<typename Func, typename... Args>
auto call(Func func, Args... args)
{
sendWork(std::bind(func, this->someMemberClass, args...)); // Async
return getResults(); // Waiting til get results
}
void waitThread()
{
//Thread waiting
// Will do the std::bind sent at sendWork
}
}
Has someone any idea?
Thank you for your time!
As mentioned in the commentaries, the only current way to pass a generic function to another thread is by using std::function<void()> which forbid any return type, but grants the ability to specify any parameters and number of parameters, in order to return results, you'll have to think about callbacks.

Put function into template

I found a thread pool class and i tried with alot of combinations to call method with function inside.
Here is example of my try :
WorkerPool wp(4);
wp.run_task<Connection::On_NET1_LOGIN>(&On_NET1_LOGIN());
Here are the WorkerPool's functions :
template < typename Task >
void run_task( Task task )
{
boost::unique_lock< boost::mutex > lock( mutex_ );
// If no threads are available, then return.
if ( 0 == available_ ) return;
// Decrement count, indicating thread is no longer available.
--available_;
// Post a wrapped task into the queue.
io_service_.post( boost::bind( &WorkerPool::wrap_task, this,
boost::function< void() >( task ) ) );
}
private:
/// #brief Wrap a task so that the available count can be increased once
/// the user provided task has completed.
void wrap_task( boost::function< void() > task )
{
// Run the user supplied task.
try
{
task();
}
// Suppress all exceptions.
catch ( ... ) {}
// Task has finished, so increment count of available threads.
boost::unique_lock< boost::mutex > lock( mutex_ );
++available_;
}
What I doing wrong in calling function to that threadpool ?
Thanks.
You are trying to add the task like this:
wp.run_task<Connection::On_NET1_LOGIN>(&On_NET1_LOGIN());
It seems there are two issues with this.
You do not need to specify template parameters, as they can be inferred. Also, if you did, you should specify the type - not the name - of the function.
You want to pass the address of the function to be called, but you are trying to call the function and take the address of the result.
To solve both these issues, try the following:
wp.run_task(&Connection::On_NET1_LOGIN);
Note: Since On_NET1_LOGIN seems to be a member function of Connection, this won't work unless the function is static. If this is not the case, you need a Connection instance to call the function on and you need to send a function object which does this. This can be solved using a lambda or std::bind.

simple callback control using boost::asio and c++11 lambda

I'm implementing simple server with boost::asio and thinking of io-service-per-cpu model(each io_service has one thread).
What i want to do is, let an io_service to request some jobs to another io_service( something like message passing ).
I think boost::asio::io_service::post can help me.
There are two io_services, ios1,ios2,
and a job(function) bool func(arg *),
and a completion handler void callback(bool).
So I want ios1 to request a job, ios2 runs it and notify ios1 to finish and finally ios2 runs the handler.
ios2.post(
[&ios1, arg_ptr, callback, func]
{
bool result = func(arg_ptr);
ios1.post( []{ callback(result) } );
} );
Is this code works? and is there any smarter and simpler way?
EDIT:
I found that the second lamda inside the ios1.post() can't reach the function pointer callback. It's out of the scope... so I'm trying another way using boost::bind().
ios2.post(
[&ios1, arg_ptr, callback, func]
{
ios1.post( boost::bind( callback, func(arg_ptr) ) );
} );
I removed one stack variable bool and it seems better.
But using c++11 lambda and boost::bind together doesn't look so cool.
How can i do this without boost::bind?
I found that the second lamda inside the ios1.post() can't reach the function pointer callback. It's out of the scope
I don't think that's the problem.
You're trying to capture callback but that's not a function pointer, it's a function. You don't need to capture a function, you can just call it! The same applies to func, don't capture it just call it. Finally, your inner lambda refers to result without capturing it.
It will work if you fix these problems:
ios2.post(
[&ios1, arg_ptr]
{
bool result = func(arg_ptr);
ios1.post( [result]{ callback(result); } );
}
);
You're second version is not quite the same, because func(arg_ptr) will get run in the thread of ios1 not ios2, and I'm not sure either version fits your description:
So I want ios1 to request a job, ios2 runs it and notify ios1 to finish and finally ios2 runs the handler.
In both your code samples ios1 runs the callback handler.
#include <boost/asio/io_service.hpp>
#include <boost/function.hpp>
typedef int arg;
int main()
{
arg * arg_ptr;
boost::function<void(bool)> callback;
boost::function<bool(arg *)> func;
boost::asio::io_service ios1, ios2;
ios2.post(
[&ios1, arg_ptr, callback, func]
{
bool result = func(arg_ptr);
auto callback1 = callback;
ios1.post( [=]{ callback1(result); } );
} );
}

How do I create a packaged_task with parameters?

Following this excellent tutorial for futures, promises and packaged tasks I got to the the point where I wanted to prepare my own task
#include <iostream>
#include <future>
using namespace std;
int ackermann(int m, int n) { // might take a while
if(m==0) return n+1;
if(n==0) return ackermann(m-1,1);
return ackermann(m-1, ackermann(m, n-1));
}
int main () {
packaged_task<int(int,int)> task1 { &ackermann, 3, 11 }; // <- error
auto f1 = task1.get_future();
thread th1 { move(task1) }; // call
cout << " ack(3,11):" << f1.get() << endl;
th1.join();
}
As far as I can decipher the gcc-4.7.0 error message it expects the arguments differently? But how? I try to shorten the error message:
error: no matching function for call to
'std::packaged_task<int(int, int)>::packaged_task(<brace-enclosed initializer list>)'
note: candidates are:
std::packaged_task<_Res(_ArgTypes ...)>::---<_Res(_ArgTypes ...)>&&) ---
note: candidate expects 1 argument, 3 provided
...
note: cannot convert 'ackermann'
(type 'int (*)(int, int)') to type 'std::allocator_arg_t'
Is my variant how I provide the parameters for ackermann wrong? Or is it the wrong template parameter? I do not give the parameters 3,11 to the creation of thread, right?
Update other unsuccessful variants:
packaged_task<int()> task1 ( []{return ackermann(3,11);} );
thread th1 { move(task1) };
packaged_task<int()> task1 ( bind(&ackermann,3,11) );
thread th1 { move(task1) };
packaged_task<int(int,int)> task1 ( &ackermann );
thread th1 { move(task1), 3,11 };
hmm... is it me, or is it the beta-gcc?
Firstly, if you declare std::packaged_task to take arguments, then you must pass them to operator(), not the constructor. In a single thread you can thus do:
std::packaged_task<int(int,int)> task(&ackermann);
auto f=task.get_future();
task(3,11);
std::cout<<f.get()<<std::endl;
To do the same with a thread, you must move the task into the thread, and pass the arguments too:
std::packaged_task<int(int,int)> task(&ackermann);
auto f=task.get_future();
std::thread t(std::move(task),3,11);
t.join();
std::cout<<f.get()<<std::endl;
Alternatively, you can bind the arguments directly before you construct the task, in which case the task itself now has a signature that takes no arguments:
std::packaged_task<int()> task(std::bind(&ackermann,3,11));
auto f=task.get_future();
task();
std::cout<<f.get()<<std::endl;
Again, you can do this and pass it to a thread:
std::packaged_task<int()> task(std::bind(&ackermann,3,11));
auto f=task.get_future();
std::thread t(std::move(task));
t.join();
std::cout<<f.get()<<std::endl;
All of these examples should work (and do, with both g++ 4.6 and MSVC2010 and my just::thread implementation of the thread library). If any do not then there is a bug in the compiler or library you are using. For example, the library shipped with g++ 4.6 cannot handle passing move-only objects such as a std::packaged_task to std::thread (and thus fails to handle the 2nd and 4th examples), since it uses std::bind as an implementation detail, and that implementation of std::bind incorrectly requires that the arguments are copyable.
Since you're starting the thread with no arguments, you expect the task to be started with no arguments, as if task1() were used. Hence the signature that you want to support is not int(int, int) but int(). In turn, this means that you must pass a functor that is compatible with this signature to the constructor of std::packaged_task<int()>. Try:
packaged_task<int()> task1 { std::bind(&ackermann, 3, 11) };
Another possibility is:
packaged_task<int(int,int)> task1 { &ackermann };
auto f1 = task1.get_future();
thread th1 { move(task1), 3, 11 };
because the constructor of std::thread can accept arguments. Here, the functor you pass to it will be used as if task1(3, 11) were used.