Amir Taaki
2012-06-26 01:00:24 UTC
According to this link:
http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/io_service.html
In the section titled "Stopping the io_service from running out of work", it says that invocating stop() on the io_service will cause the run() function to return as soon as possible, abandoning unfinished operations without dispatching them.
I created a simple program to test this and it works fine. After calling stop, all the waiting handlers are discarded and the io_service finishes immediately. See http://ideone.com/1dWDK
However, if I then use a strand, it will not finish but continue on until *all* the pending work has been completed. This is really annoying because my use is serialising access to a shared resource. Each query takes a very long time, and there's many of them. This means that when the program wants to exit, it needs to wait for all these very long pending pieces of work to complete before the database can be shut down.
Real code:
https://gitorious.org/libbitcoin/libbitcoin/blobs/master/src/blockchain/bdb/bdb_blockchain.cpp
Example testcase:
http://ideone.com/ND9tu
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
using boost::asio::io_service;
class foo
{
public:
foo(io_service& service)
: strand_(service) {}
void bar()
{
strand_.post(
[this]
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
sleep(1);
});
}
private:
io_service::strand strand_;
};
int main()
{
io_service service;
io_service::work* work = new io_service::work(service);
std::thread t([&service] { service.run(); });
foo f(service);
// Only 5 bar()s should get called, but instead all 10 are allowed to finish...
for (size_t i = 0; i < 10; ++i)
f.bar();
sleep(5);
std::cout << "Closing" << std::endl;
//delete work;
//work = nullptr;
service.stop();
t.join();
return 0;
}
http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/io_service.html
In the section titled "Stopping the io_service from running out of work", it says that invocating stop() on the io_service will cause the run() function to return as soon as possible, abandoning unfinished operations without dispatching them.
I created a simple program to test this and it works fine. After calling stop, all the waiting handlers are discarded and the io_service finishes immediately. See http://ideone.com/1dWDK
However, if I then use a strand, it will not finish but continue on until *all* the pending work has been completed. This is really annoying because my use is serialising access to a shared resource. Each query takes a very long time, and there's many of them. This means that when the program wants to exit, it needs to wait for all these very long pending pieces of work to complete before the database can be shut down.
Real code:
https://gitorious.org/libbitcoin/libbitcoin/blobs/master/src/blockchain/bdb/bdb_blockchain.cpp
Example testcase:
http://ideone.com/ND9tu
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
using boost::asio::io_service;
class foo
{
public:
foo(io_service& service)
: strand_(service) {}
void bar()
{
strand_.post(
[this]
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
sleep(1);
});
}
private:
io_service::strand strand_;
};
int main()
{
io_service service;
io_service::work* work = new io_service::work(service);
std::thread t([&service] { service.run(); });
foo f(service);
// Only 5 bar()s should get called, but instead all 10 are allowed to finish...
for (size_t i = 0; i < 10; ++i)
f.bar();
sleep(5);
std::cout << "Closing" << std::endl;
//delete work;
//work = nullptr;
service.stop();
t.join();
return 0;
}