[asio] posting a function to an io_service object

Hi, I am trying to call a function by posting it to an io_service object running in a different thread from the main thread of the application. The problem is the function always gets called from the main thread. Basically I would like to do this with asio: #include <iostream> #include <boost/thread.hpp> using namespace std; void f() { cout << boost::this_thread::get_id() << endl; } int main(int argc, char *argv[]) { cout << "main thread: " << boost::this_thread::get_id() << endl; boost::thread t1(f); boost::thread t2(f); t1.join(); t2.join(); return 0; } The output is: main thread: 0x9739628 0x97392e8 0x9739488 Using Boost.Asio, f() always gets called from the main thread: #include <iostream> #include <boost/bind.hpp> #include <boost/thread.hpp> #include <boost/asio.hpp> using namespace std; using namespace boost::asio; void f() { cout << boost::this_thread::get_id() << endl; } int main(int argc, char *argv[]) { io_service ios1; io_service ios2; io_service::work w1(ios1); io_service::work w2(ios2); io_service::strand s1(ios1); io_service::strand s2(ios2); boost::thread t1(boost::bind(&io_service::run, &ios1)); boost::thread t2(boost::bind(&io_service::run, &ios2)); cout << "main thread: " << boost::this_thread::get_id() << endl; //s1.post(f); //s2.post(f); ios1.post(s1.wrap(f)); ios2.post(s2.wrap(f)); while (ios1.poll() > 0) ; while (ios2.poll() > 0) ; ios1.stop(); ios2.stop(); t1.join(); t2.join(); return 0; } The output is: main thread: 0x9739628 0x9739628 0x9739628 What is the correct way of posting/dispatching a function to an io_service running in a different thread, so that function is called from that thread? Thanks Vil

Using Boost.Asio, f() always gets called from the main thread:
You use io_service incorrectly, please see asio tutorial/examples.
while (ios1.poll() > 0) ; while (ios2.poll() > 0) ;
io_services are already running - in other threads - why do you poll() them here?

You use io_service incorrectly, please see asio tutorial/examples.
while (ios1.poll() > 0) ; while (ios2.poll() > 0) ;
io_services are already running - in other threads - why do you poll() them here? In this example, poll() is there to execute the f() handlers and wait for them to finish.
You are right, not polling the io_services from the main thread makes the f() calls run in the other threads as intended. In that case is there a way to check from the main thread if the io_services finished executing the posted handlers (some kind of a peek())? I have a program where there are several parallel io_threads and I want to run two distinct library functions in each io_service first thing an io_service is started and last thing before an io_service is stopped. These functions are posted from the main thread. My problem is with the function that is to be executed last: how can I wait for that to be executed before stopping the io_service and joining the thread? Calling poll()/dispatch() from the main thread is not an option, it seems. Vil

My problem is with the function that is to be executed last: how can I wait for that to be executed before stopping the io_service and joining the thread?
Usually you don't have to stop io_service explicitly - when it runs out of work, it stops by its own. So if all you need is to perform several functions/functors on io_service thread - just post them to io_service, and join io_service thread(s): // pseudo-code! { asio::io_service io; io_.post(functor1); io_.post(functor2); thread t(&io_service::run, &io); t.join(); // when io_service runs out of jobs, run() exits. } If you need to get more control over io_service::run "lifetime", you can use work object, like in your example: // pseudo-code! { asio::io_service io; shared_ptr<io_service::work> work(new io_service::work(ios)); thread t(&io_service::run, &io); io_.post(functor1); io_.post(functor2); // do something... // when there's not more real work, and all the copies of "work" shared ptr are reset, io_service::run will exit t.join(); } If you still need to get synchronized with one of your functors being executed in another thread, use boost::condition_variable (the functor sets condition, main thread waits for condition): http://www.boost.org/doc/libs/1_41_0/doc/html/thread/synchronization.html#th...

Thank you for your answer, Igor. I need a work object as the io_service not always has real work to do, resetting the work shared_ptr before join() is the right solution for me. A conditional variable is definitely a more elegant approach, I might give it a go. :) Happy new year to you all. Vil

-----Original Message-----
You are right, not polling the io_services from the main thread makes the f() calls run in the other threads as intended. In that case is there a way to check from the main thread if the io_services finished executing the posted handlers (some kind of a peek())?
The run command will return if you get rid of the two work objects. Then, you could just wait for the threads to join.
I have a program where there are several parallel io_threads and I want to run two distinct library functions in each io_service first thing an io_service is started and last thing before an io_service is stopped. These functions are posted from the main thread. My problem is with the function that is to be executed last: how can I wait for that to be executed before stopping the io_service and joining the thread? Calling poll()/dispatch() from the main thread is not an option, it seems.
Look into writing a custom service object. I think that the logging example is a good place to start. There is an entry point that gets called when the io_service is being stopped. ~Dan
participants (3)
-
Casimiro, Daniel C CIV NUWC NWPT
-
Igor R
-
Vilhelm Sundberg