I have a problem while using deadline_timer and io_service::post as below:
#include "boost/asio.hpp"
#include "boost/thread.hpp"
int main()
{
boost::asio::io_service io_service;
boost::asio::deadline_timer timer1(io_service);
boost::asio::deadline_timer timer2(io_service);
timer1.expires_from_now(boost::posix_time::seconds(1));
timer1.async_wait([](const boost::system::error_code& error) {
boost::this_thread::sleep(boost::posix_time::seconds(5));
printf("1 ");
});
timer2.expires_from_now(boost::posix_time::seconds(2));
timer2.async_wait([](const boost::system::error_code& error) {
printf("2 ");
});
boost::thread t([&io_service]() {
boost::this_thread::sleep(boost::posix_time::seconds(5));
io_service.post([]() {
printf("3 ");
});
io_service.post([]() {
printf("4 ");
});
});
io_service.run();
t.join();
getchar();
return 0;
}
I thougth that the result is "1 2 3 4" but the result is "1 3 4 2". Anyone can show me how to the callback of timer2(print "2") is performed before as the result "1 2 3 4" with boost library (and don't change the expire time of timer1 and timer2).
Thanks very much!
This is actually a pretty complicated example.
The io_service will run on the main thread. Here is the order of operations
Main Thread:
Request Timer at T0 + 1
Request Timer at T0 + 2
Spawn thread
Execute all pending io (io_service.run())
Secondary Thread:
Sleep 5 seconds
Request Timer
Request Timer
First of all, nothing will execute in the io_service until io_service.run() is called.
Once io_service.run() is called, a timer for 1 second in the future is scheduled. When that timer fires, it first sleeps for 5 seconds before printing 1.
While that thread is executing, the secondary thread also comes up, and sleeps for 5 seconds. This thread is setup and scheduled before the timer executing in the handler for timer1 is completed. Since both of these threads sleep for 5 seconds, '2' and '3' are immediately posted to the io_service.
Now things get a bit tricky. It seems likely that the timeout for timer2 should have expired by now (it being at least 5 seconds in the future), but there were two commands directly posted to the io_service while it was handling timer1.
It seems that in the implementation details, boost gives priority to directly posted actions over deadline timer actions.
the first timer expiration blocks the io (main) thread from running, in the mean time the other thread posts a couple of items to asio work queue, once timer 1's callback completes, the second timers expiration is processed which causes the callback to be queued but not executed. since "3" & "4" where already queued (while "1" was blocking the main thread), they go ahead of "2"
The point of asio is to not block. By putting long running work in the first timers callback (the sleep) you have prevented the io thread from running in a timely manner. You should offload that work into a dedicated thread, and post its completion back to asio.
The io_service makes no guarantees about the invocation order of handlers. In theory, the handlers could be invoked in any order, with some permutations being significantly unlikely.
If handlers need to be invoked in a very specific order, then consider restructing the asynchronous call chains in a manner that enforces the desired handler chain. Additionally, one may find it necessary to use the guaranteed order of handler invocation that strand provides. Consider not trying to control complex handler invocations through with brittle sleeps and timers.
Your first problem is that you're trying to block inside a handler:
timer1.expires_from_now(boost::posix_time::seconds(1));
timer1.async_wait([](const boost::system::error_code& error) {
boost::this_thread::sleep(boost::posix_time::seconds(5)); // <--- HERE
printf("1 ");
});
What happens in the above code is that after timer1 waits for one second, it posts the callback to the io_service. Inside the io_service::run function this callback is executed but this execution happens inside the main thread, so it halts for five seconds, preventing timer2 from posting its handler for execution into io_service. It does so until the sixth second of the program execution (6 = 5+1).
Meanwhile the thread t gets executed and at fifth second of program execution it posts those two printf("3") and printf("4") to io_service.
boost::thread t([&io_service]() {
boost::this_thread::sleep(boost::posix_time::seconds(5));
io_service.post([]() {
printf("3 ");
});
io_service.post([]() {
printf("4 ");
});
});
Once the handler from timer1 unblocks, it allows timer2 to post its handler to io_service. That again happens at sixth second of program exectuion, that is, once the printf("3") and printf("4") have already been posted!
All in all, I believe what you're looking for is this:
#include "boost/asio.hpp"
#include "boost/thread.hpp"
int main()
{
boost::asio::io_service io_service;
boost::optional<boost::asio::io_service::work> work(io_service);
boost::asio::deadline_timer timer1(io_service);
boost::asio::deadline_timer timer2(io_service);
timer1.expires_from_now(boost::posix_time::seconds(1));
timer1.async_wait([](const boost::system::error_code& error) {
printf("1 ");
});
timer2.expires_from_now(boost::posix_time::seconds(2));
timer2.async_wait([](const boost::system::error_code& error) {
printf("2 ");
});
boost::thread t([&io_service, &work]() {
boost::this_thread::sleep(boost::posix_time::seconds(5));
io_service.post([]() {
printf("3 ");
});
io_service.post([&work]() {
printf("4 ");
work = boost::none;
});
});
io_service.run();
t.join();
return 0;
}
Related
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.
I am working with the boost::asio tcp, version 1.57, creating a custom server/client, roughly following this example: Async_Tcp_Client , but I'm running the io_service run() in it's own thread per server/client. Also, there can be multiple server/clients per application.
Following the example I put my await_output function to sleep when I DON'T want to send a Message, and waking it up when I do want to send one (via async_write). After a varying amount of send-operations (sometimes less then 10, sometimes several thousand) I run into strange behaviour of my await_output Deadline (a boost deadline timer).
At some point, the async_wait against the timer just "disappears" and doesn't return when I cancel the deadline to send a message.
The transmit function, that is called by the Application owning the Client/Server (only by the application though, I guess it is not very threadsafe);
The await_output function that is waiting on the mOutputQueueDeadline;
And the handle_write function:
void SocketTcp::transmit(std::string pMsg) {
if (mStopped)
{ return; }
mOutputQueue.push(pMsg); // a global queue
// Signal that the output queue contains messages. Modifying the expiry
// will wake the output actor, if it is waiting on the timer.
size_t quits = mOutputQueueDeadline.expires_at(boost::posix_time::neg_infin);
//this returns '0' when the error occurs
}
void SocketTcp::await_output(const boost::system::error_code& ec)
{
if (mStopped)
{ return; }
if (mOutputQueue.empty())
{
size_t quits = mOutputQueueDeadline.expires_at(boost::posix_time::pos_infin);
mOutputQueueDeadline.async_wait(boost::bind(&SocketTcp::await_output, this, _1));
//this async_wait starts a wait on the deadline, that sometimes never returns!
}
else
{
boost::asio::async_write(mSocket,
boost::asio::buffer(mOutputQueue.front()),
boost::bind(&SocketTcp::handle_write, this, _1));
}
}
void SocketTcp::handle_write(const boost::system::error_code& ec)
{
if (mStopped)
{ return; }
if(!ec)
{
mOutputQueue.pop(); //remove sent element from queue
boost::system::error_code errcode;
await_output(errcode); //start the waiting actor for outgoing messages
}
else
{
mConnected = false; //update the connection status
this->stop();
}
}
I tried implementing a workaround, restarting the await_output in transmit() when expire_at returns 0, but that leads to TWO actors beeing awakened the next time I send a message, and then running into a crash (String iterator not dereferencable - the design doesn't allow for parallel send OP, much less trying to send the same message...)
I tried debugging with the BOOST_ASIO_ENABLE_HANDLER_TRACKING option, and found the error here:
#asio|1468415460.456019|0|deadline_timer#000000000050AB88.cancel //transmit cancels the timer
#asio|1468415460.456019|>474|ec=system:995 //await_output is called
#asio|1468415460.456019|474*479|socket#000000000050A9D8.async_send //starts the async send
#asio|1468415460.457019|<474|
#asio|1468415460.457019|>479|ec=system:0,bytes_transferred=102 //async send returns to it's handler
#asio|1468415460.457019|479|deadline_timer#000000000050AB88.cancel
//this cancel op is the only difference to the 'normal' order,
//not sure where it originates though!!
#asio|1468415460.457019|479*480|deadline_timer#000000000050AB88.async_wait //the handler starts the new async wait
//handler 480 never gets called when the deadline is canceled the next time
#asio|1468415460.457019|<479|
I'm pretty new to c++ as well as the stackoverflow (even though it has already safed me multiple times!) so please tell me if I can improve my question somehow!
I have a thread pool which executes tasks asynchronously. But I need to wait for a certain task to complete before proceeding (running the task in current thread is not allowed, the task must be run by a worker thread).
What's the easiest way to achieve this using C++11 or Boost?
pool.enqueue([]() {
std::this_thread::sleep_for(2s); // task 1
// notify task 1 completion???
std::this_thread::sleep_for(2s); // task 2
});
// wait until task 1 is complete???
If you have a thread pool, either the pool should handle the dependencies or
you should chain the continuation task from the first task directly.
Otherwise, the pool can deadlock. Imagine just for example a pool with 1 thread. It would block indefinitely. Same can occur with many threads given enough task inter dependencies.
Use std::condition_variable:
std::mutex m;
bool task1_done=false;
std::condition_variable cond_var;
pool.enqueue([&cond_var, &task1_done]() {
std::this_thread::sleep_for(2s); // task 1
// notify task 1 completion
task1_done=true;
cond_var.notify_one();
std::this_thread::sleep_for(2s); // task 2
});
// wait until task 1 is complete
std::unique_lock<std::mutex> lock(m);
while( !task1_done ) {
cond_var.wait(lock);
}
You can use mutex and wait_for/wait_until
You can look example
Going to answer my own question.
I ended up using a future:
std::packaged_task<int()> task1([]() {
std::this_thread::sleep_for(2s); // task 1
return 1;
});
std::future<int> task1result = task1.get_future();
std::thread thread1([&]() {
task1();
std::this_thread::sleep_for(2s); // task 2
});
int rc1 = task1result.get();
printf("task1 complete: %d\n", rc1);
thread1.join();
printf("thread complete\n");
And no, there is no chance for a deadlock since there is no cyclic dependency between the threads (the waiting thread is not part of the pool).
I have a multithreaded C++ Windows application. The worker thread is an infinite loop waiting for events to process, one of which is a kill thread event from main thread. The problem is that sometimes it takes a really long time (think seconds) for the worker thread to receive the kill event and terminate. Other times it's very quick (milliseconds).
// Main thread code
void deactivate()
{
while (isWorkerThreadRunning)
{
// Problem: sometimes it spends a long time in this loop
logDebug("deactivate: killing worker thread");
SetEvent(killWorker);
Sleep(20);
}
}
// Worker thread code
DWORD WINAPI WorkerThreadProc(LPVOID arglist)
{
isWorkerThreadRunning = true;
logDebug("Worker thread started");
for (bool done = false; done != true; )
{
HANDLE handles[3] = { killWorker, action1, action2 };
DWORD rc = WaitForMultipleObjects(3, handles, FALSE, INFINITE);
switch (rc)
{
case WAIT_OBJECT_0 + 0: done = true; break;
case WAIT_OBJECT_0 + 1: doAction1(); break;
case WAIT_OBJECT_0 + 2: doAction2(); break;
default: logWarn("Unhandled wait signal");
}
}
isWorkerThreadRunning = false;
logDebug("Worker thread killed");
return 0;
}
I believe that if the worker thread receives a kill event while it is busy inside doAction1() or doAction2() the kill event won't be received and processed until doAction1() or doAction2() is completed and returned. And if doAction1() or doAction2() takes a long time to return then the worker thread will take a long time to exit.
However, I have log points sprinkled throughout doAction1() and doAction2() but I don't see any of those log points in the log file. All I see are:
deactivate: killing worker thread
deactivate: killing worker thread
deactivate: killing worker thread
deactivate: killing worker thread
//....many more times
Worker thead killed
which means the worker thread is not doing any work but rather waiting inside the WaitForMultipleObjects() call.
The question is why is the WaitForMultipleObjects() call sometimes take a long time (and sometimes very quick) to signal the waiter of an event??
Would changing the timeout from INFINITE to some reasonable number fix this problem?
Thanks,
Your declaration of isWorkerThreadRunning should be volatile if it is not. You can get some strange behavior when the compiler optimizes the code if it is not volatile.
volatile bool isWorkerThreadRunning;
I would also suggest entry and exit messages in your doAction functions. That will make it clearer if you're still inside one of those functions when the exit signal is sent.
I use boost asio to handle a session per thread like this:
Server::Server(ba::io_service& ioService, int port): ioService_(ioService), port_(port)
{
ba::ip::tcp::acceptor acceptor(ioService_, ba::ip::tcp::endpoint(ba::ip::tcp::v4(), port_));
for (;;)
{
socket_ptr sock(new ba::ip::tcp::socket(ioService_));
acceptor.accept(*sock);
boost::thread thread(boost::bind(&Server::Session, this, sock));
}
}
void Server::Session(socket_ptr sock)
{
const int max_length = 1024;
try
{
char buffer[256] = "";
// HandleRequest() function performs async operations
if (HandleHandshake(sock, buffer))
HandleRequest(sock, buffer);
ioService_.run();
}
catch (std::exception& e)
{
std::cerr << "Exception in thread: " << e.what() << "\n";
}
std::cout << "Session thread ended \r\n"; // THIS LINE IS NEVER REACHED
}
In Server::Session() I do at some point async io using async_read_some() and async_write() functions.
All works well and in order for this to work I have to have a call to ioService_.run() inside my spawn thread otherwise Server::Session() function exits and it does not process the required io work.
The problem is that ioService_.run() called from my thread will lead for the thread not to exit at all because in the meantime other requests come to my listening server socket.
What I end up with is threads starting and processing for now sessions but never releasing resources (ending). Is it possible to use only one boost::asio::io_service when using this approach ?
I believe you are looking for run_one() or poll_one() this will allow you to have the thread either execute a ready handler (poll) or wait for a handler (run). By only handling one, you can pick how many to execute before exiting your thread. As opposed to run() which executes all the handlers until the io_service is stopped. Where as poll() would stop after it handled all the ones that are currently ready.
The way I structured handling connection here was bad.
There is quite a good video presentation about how to design your asio server bellow(made by asio creator)
Thinking Asynchronously: Designing Applications with Boost Asio