boost asio behaviour - calling ios_service::run from multiple threads - c++

I am trying to use boost::asio deadline timer for delayed function call as follows
#include <boost/asio.hpp>
#include "boost/thread.hpp"
#include <iostream>
class MyTest {
public:
MyTest()
:_invokeCount(0),
_handleCount(0)
{}
void handler(int i)
{
std::cout<<"\t\tHandled " <<i << std::endl;
++_handleCount;
}
void RunIOService()
{
std::cout<<"\tStarted :"<< _invokeCount<< std::endl;
_ios.run();
std::cout<<"\tFinished "<< _invokeCount << std::endl;
}
void invokeTimer()
{
std::cout<<"invoked " << ++_invokeCount << std::endl;
boost::asio::deadline_timer t(_ios, boost::posix_time::milliseconds(5));
t.async_wait(boost::bind(&MyTest::handler, this, _invokeCount));
boost::thread th = boost::thread(boost::bind(&MyTest::RunIOService, this));
}
void PrintCount()
{
std::cout<<"Count = "<< _invokeCount << std::endl;
}
void Wait()
{
while (_invokeCount > _handleCount) {
std::cout<<"X ";
Sleep(1000);
}
}
private:
int _invokeCount;
int _handleCount;
boost::asio::io_service _ios;
};
int main(int argc, char* argv[])
{
MyTest test;
for (int k=0; k<5; ++k) {
test.invokeTimer();
Sleep(40);
}
test.Wait();
test.PrintCount();
return EXIT_SUCCESS;
}
The output of this application is not as I expected:-
invoked 1
Started :1
Handled 1
Finished 1
invoked 2
Started :2
Finished 2
invoked 3
Started :3
Handled 2
Finished 3
invoked 4
Started :4
Handled 3
Finished 4
invoked 5
Started :5
Handled 4
Finished 5
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I expected every handler to be called before ios_service::run returns and it doesn't seem so from the output ( missing output between Started:2 and Finished:2). Also, the application never exits. i.e the 5th handler never gets invoked.
What am I missing?
Thanks!

A couple of things:
You probably don't need 5 threads. Why don't you create a single thread and fire the events into that single ioservice instance running in the thread
Try using io_service::work in the thread run function to keep the io_service in scope while all your requests are handled.
When your wait finishes, stop your io_service, join your thread and let your program exit
Read here about io_service::work: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/io_service.html

I added ios_service::reset() after each ios_service::run() and it worked as expected.

boost::asio::ioservice::reset() should be called before later set of invocations of the run().
as the boost doc say:
This function must be called prior to any second or later set of invocations of the run(), run_one(), poll() or poll_one() functions when a previous invocation of these functions returned due to the io_service being stopped or running out of work. This function allows the io_service to reset any internal state, such as a "stopped" flag.
This function must not be called while there are any unfinished calls to the run(), run_one(), poll() or poll_one() functions.

Related

Understanding how multithreading works with Boost io_service

I'm learning multithreading and Boost libraries (Asio in particular) and I'm having a hard time understanding how the following code works (slightly modified from Boost.org tutorials)
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
class printer
{
public:
printer(boost::asio::io_service& io)
: timer1_(io, boost::posix_time::seconds(1)),
timer2_(io, boost::posix_time::seconds(1)),
count_(0)
{
timer1_.async_wait(boost::bind(&printer::print1, this));
timer2_.async_wait(boost::bind(&printer::print2, this));
}
~printer()
{
std::cout << "Final count is " << count_ << std::endl;
}
void print1()
{
if (count_ < 10)
{
std::cout << "Timer 1: " << count_ << std::endl;
++count_;
timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(2));
timer1_.async_wait(boost::bind(&printer::print1, this));
}
}
void print2()
{
if (count_ < 10)
{
std::cout << "Timer 2: " << count_ << std::endl;
++count_;
timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(2));
timer2_.async_wait(boost::bind(&printer::print2, this));
}
}
private:
boost::asio::deadline_timer timer1_;
boost::asio::deadline_timer timer2_;
int count_;
};
void saysomething()
{
std::string whatyasay;
std::cin >> whatyasay;
std::cout << "You said " << whatyasay << std::endl;
}
int main()
{
boost::asio::io_service io;
printer p(io);
boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
io.run();
std::cout << "Hey there\n";
t.join();
return 0;
}
Which results in the following output
Timer 1: 0
Timer 2: 1
Timer 1: 2
Timer 2: 3
Timer 1: 4
Timer 2: 5
Timer 1: 6
Timer 2: 7
Timer 1: 8
Timer 2: 9
Hey there
Final count is 10
What I would've expected from this code was that thread t would be in charge of running the io_service, meaning that other operations could take place in the meantime.
Instead, the code behaves as usual, aka, io.run "blocks" the code flow until the timers inside the printer object stop launching async_waits, so "hey there" is only printed after the timers are not working anymore.
But that's not all: from my understanding, io_services don't stop running after the run() method is called as long as there's work associated to them (be it a work object or, in this case, timers). With that said, since the thread is associated to the io_service, I wonder why the io_service would stop running in the first place: after all, the thread is "linked" to the io_service and keeps on running on its own; this is obviously linked to the fact that I clearly didn't understand what this thread is doing in the first place.
Things got even more complicated when I added the "saysomething" method into the pot: I wanted to be able to write something and having that string printed WHILE the 2 timers kept working. The code I used was the following:
int main()
{
boost::asio::io_service io;
printer p(io);
boost::thread t(&saysomething);
io.run();
std::cout << "Hey there\n";
t.join();
return 0;
}
With the following result:
Timer 1: 0
Timer 2: 1
Timer 1: 2
Timer 2: 3
Timer 1: 4
Timer 2: 5
Timer 1: 6
Timer 2: 7
ghg //<--- my input
You said ghg
Timer 1: 8
Timer 2: 9
Hey there
Final count is 10
It works fine, but now that there is no thread associated to the io_service, what was its purpose in the first place?
To sum up my 3 questions are:
Why isn't the "Hey there" string immediately printed rather than waiting for the io_service to stop running?
How exactly does the io_service stop running if a thread is linked to it, which should be equivalent to the io_service having work to do?
Since the thread wasn't allowing the "code flow" to move forward, and linking said thread to my method instead of the io_service didn't cause any error, what was the purpose of that thread in the first place?
Why isn't the "Hey there" string immediately printed rather than waiting for the io_service to stop running?
main's thread also blocks on the io_service before printing, so "Hey there" doesn't print until the service stops.
How exactly does the io_service stop running if a thread is linked to it, which should be equivalent to the io_service having work to do?
The thread is not what's keeping the io_service alive, the timer tasks are. The io_service is actually the one keeping the thread alive here. The work the service has is waiting on the timers, so until the timers expire, the service has work to do.
Since the thread wasn't allowing the "code flow" to move forward, and linking said thread to my method instead of the io_service didn't cause any error, what was the purpose of that thread in the first place?
The purpose of calling run from a thread is to donate that calling thread to the io_service. Until run exits, the service owns that thread, and that thread is part of the service's thread pool. Any task you post to the service may be handed to that thread while it is in the service's pool. When you added the second thread, that second thread wasn't interacting with the service at all because it didn't call run. Thus, it's not part of the service's thread pool.

boost asio timer : run 2 timers

I try to run a asynchronous timer and a synchronous timer :
Here is my code :
boost::asio::io_service io;
boost::asio::steady_timer t1(io);
boost::asio::steady_timer t2(io);
void callback(boost::system::error_code const&)
{
std::cout << "foo" << std::endl;
t1.expires_from_now(boost::chrono::seconds(1));
t1.async_wait(&callback);
}
int main(int argc, char **argv)
{
t1.expires_from_now(boost::chrono::seconds(1));
t1.async_wait(&callback);
io.run();
t2.expires_from_now(boost::chrono::seconds(5));
t2.wait();
io.run();
std::cout << "finish" << std::endl;
return EXIT_SUCCESS;
}
I would like foo to printed 5 times, and finish printed.
In this code, foo is printed every 1 second and finish is never reached.
How to achieve what I want ?
Thanks
According to the documentation of io_service::run:
The run() function blocks until all work has finished and there are no more handlers to be dispatched, or until the io_service has been stopped.
Since run blocks until there are no more handlers to be dispatched, it will block until callback has finished. However, callback registers another callback handler and run will keep blocking until it's finished... ad infinitum
If you want the callback to repeat only five times, then you need to not schedule a new callback after the fifth time.You can use a simple counter and a branch for that.
As said in user2079303's answer, your first io.run() call never returns since callback registers itself.
To achieve what you want to do, you can just modify your callback function as followed:
void callback(boost::system::error_code const&)
{
static int i = 0;
std::cout << "foo" << std::endl;
t1.expires_from_now(boost::chrono::seconds(1));
if (++i < 5) {
t1.async_wait(&callback);
} else {
i = 0; // Reset i if you want to reuse callback later with the same behaviour
}
}

Basic timer with std::thread and std::chrono

I'm trying to implement a basic timer with the classic methods: start() and stop(). I'm using c++11 with std::thread and std::chrono.
Start method. Creates a new thread that is asleep for a given interval time, then execute a given std::function. This process is repeated while a 'running' flag is true.
Stop method. Just sets the 'running' flag to false.
I created and started a Timer object that show "Hello!" every second, then with other thread I try to stop the timer but I can't. The Timer never stops.
I think the problem is with th.join()[*] that stops execution until the thread has finished, but when I remove th.join() line obviously the program finishes before the timer start to count.
So, my question is how to run a thread without stop other threads?
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
class Timer
{
thread th;
bool running = false;
public:
typedef std::chrono::milliseconds Interval;
typedef std::function<void(void)> Timeout;
void start(const Interval &interval,
const Timeout &timeout)
{
running = true;
th = thread([=]()
{
while (running == true) {
this_thread::sleep_for(interval);
timeout();
}
});
// [*]
th.join();
}
void stop()
{
running = false;
}
};
int main(void)
{
Timer tHello;
tHello.start(chrono::milliseconds(1000),
[]()
{
cout << "Hello!" << endl;
});
thread th([&]()
{
this_thread::sleep_for(chrono::seconds(2));
tHello.stop();
});
th.join();
return 0;
}
Output:
Hello!
Hello!
...
...
...
Hello!
In Timer::start, you create a new thread in th and then immediately join it with th.join(). Effectively, start won't return until that spawned thread exits. Of course, it won't ever exit because nothing will set running to false until after start returns...
Don't join a thread until you intend to wait for it to finish. In this case, in stop after setting running = false is probably the correct place.
Also - although it's not incorrect - there's no need to make another thread in main to call this_thread::sleep_for. You can simply do so with the main thread:
int main()
{
Timer tHello;
tHello.start(chrono::milliseconds(1000), []{
cout << "Hello!" << endl;
});
this_thread::sleep_for(chrono::seconds(2));
tHello.stop();
}
Instead of placing the join in start place it after running = false in stop. Then the stop method will effectively wait until the thread is completed before returning.

How to wake or terminate a sleeping std::thread gracefully?

#include <thread>
#include <chrono>
using namespace std:
void f()
{
// Sleeping for a very long while
while (SOCKET s = accept(listening_socket, ...))
{
// ...
}
}
int main()
{
std::thread t(f);
DoSomething();
t.???(); /* What to place here to wake/terminate thread f? */
}
Under Win32, I can use TerminateThread() to kill a thread. But what I want is a cross-platform method to do that.
How should I do that gracefully in C++?
I would recommend sleeping on a broadcast signal, semaphore, condition variable, or something instead of doing a blocking sleep. Then your application just sets the signal and anyone that is sleeping will wake up and can exit. It is a much cleaner solution since it gives the thread body a chance to cleanup whatever it might be doing - including releasing locks!
Response to Update
In this specific case, call select with a timeout before you call accept.
The first issue comes from blocking mode socket accept, you should use non-blocking socket mode.
You can set a flag in while loop, for example:
struct AcceptHandler
{
AcceptHandler()
: is_terminated(false)
{
}
void accept()
{
while(!is_terminated)
{
// select
// accept
cout << " in loop " << endl;
}
}
void terminate()
{
is_terminated = true;
}
private:
std::atomic<bool> is_terminated;
};
int main()
{
AcceptHandler ah;
std::thread t(std::bind(&AcceptHandler::accept, std::ref(ah)));
t.join(); /// this is just demo, it blocks here
ah.terminate();
return 0;
}
I used a flag(is_terminated) in the sample you could use condition variable(preferred way).

troubles with boost::asio::io_service::poll()

the following code:
/***************************************************************************/
boost::mutex m;
struct func {
func(int v):n(v) {}
void operator()() {
{ boost::mutex::scoped_lock l(m);
std::cout << "run function " << n << std::endl;
}
for ( int idx = 0; idx < 4; ++idx ) {
{ boost::mutex::scoped_lock l(m);
std::cout << "function " << n << ", ping " << idx << std::endl;
}
sleep(1);
}
}
private:
int n;
};
/***************************************************************************/
int main(int argv, const char** argc) {
boost::asio::io_service io;
for ( int idx = 0; idx < 4; ++idx ) {
io.post(func(idx));
}
std::cout << "before run" << std::endl;
io.poll();
std::cout << "after run" << std::endl;
std::cin.get();
return 0;
}
/***************************************************************************/
gives such an output:
**before run**
run function 0
function 0, ping 0
function 0, ping 1
function 0, ping 2
function 0, ping 3
run function 1
function 1, ping 0
function 1, ping 1
function 1, ping 2
function 1, ping 3
run function 2
function 2, ping 0
function 2, ping 1
function 2, ping 2
function 2, ping 3
run function 3
function 3, ping 0
function 3, ping 1
function 3, ping 2
function 3, ping 3
**after run**
but, according to the documentation:
The poll() function runs handlers that
are ready to run, without blocking,
until the io_service has been stopped
or there are no more ready handlers.
poll() - is a non-blocking method.
what's the problem?
and the second question:
in documentation it is said that:
return The number of handlers that
were executed.
if it is non-blocking, what value it will return? - the number of objects in the queue? - but this is not the same thing as "that were executed".
This is an old question but you never really got an answer about run vs poll.
io_service::run will keep running as long as there is something to do, such as waiting on a deadline timer or IO completion notification, etc. This is why there is the work object to keep run from exiting.
io_service::poll will only execute ready handlers, and will not return until there are no more handlers ready to be dispatched.
The difference in other words is that run will wait for a pending handler to be ready, like a timer or IO completion notification, while poll will return in that situation.
This behavior is useful if you want to perform some idle processing.
Non-blocking is not the same as asynchronous. pool synchronously runs handlers that are ready to run, and returns without blocking and waiting for another handlers.
Additional explanation.
Blocking input operation is operation which starts endless wait if no input data found. Consider Read operation which is supposed to read one byte from some port, but there is no incoming data. In this case Read call hangs, and returns only when byte is received. Non-blocking read operation returns immediately, if there is no input information.
pool operation is non-blocking. It synchronously executes all pending requests and returns. If there are no incoming requests, poll returns immediately.