boost::asioライブラリに複数の io_service::run の正しい呼び出し方

幾日の前に、私はboost::asioを遊んでた。こういうコードを書いた


#include
#include
#include
#include

using std::cout;
using std::endl;
using namespace boost;
using namespace boost::asio;

io_service ioserv;
mutex m;
volatile int c = 0;

void add() {
lock_guard g(m);
++c;
}

int main() {
thread t1(bind(&io_service::run, ref(ioserv)));
thread t2(bind(&io_service::run, ref(ioserv)));
for(int i = 0; i < 655360; ++i)
ioserv.post(&add);
t1.join();
t2.join();
cout << c << endl;
return 0;
}

期望の結果は655360だけど、実際にほとんど毎度試行すると結果は不同だった。
よく考えたら、任務を追加するとき、追加の速さは執行のより遅いから、追加し切れたまえにスレッドは停止した。だから、下記のように編集した:

(略)
int main() {
thread t1(bind(&io_service::run, ref(ioserv)));
thread t2(bind(&io_service::run, ref(ioserv)));
for(int i = 0; i < 655360; ++i)
ioserv.post(&add);
ioserv.run();
t1.join();
t2.join();
cout << c << endl;
return 0;
}
こう編集しても正しくなれなかった。試行したら毎度の結果も不同だった。たまに655360は出るが意味ない。

どうしたら良いでしょうかって思って、この問題はboostのメールリストの[user]に提出した。
そして、原因はわかった。
boost::asioのマニュアルに、io_service::reset関数の説明にこういう説明がある:

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.


orz.......


OK、わかった。


(略)
int main() {
thread t1(bind(&io_service::run, ref(ioserv)));
thread t2(bind(&io_service::run, ref(ioserv)));
for(int i = 0; i < 655360; ++i)
ioserv.post(&add);
t1.join();
t2.join();
ioserv.reset();
ioserv.run();

cout << c << endl;
return 0;
}
こう編集したら、655360はちゃんと出た。

Lars Viklundさん、Igor Rさん、ありがとうございます!

http://thread.gmane.org/gmane.comp.lib.boost.user/66867