signal handler with signal_set

前にnon-staticなメンバー関数をシグナルハンドラとして実行する汚いクラスをネタに記事を投稿しました。
すると、アキラさんから本ブログ初の「Boost.Asioのsignal_setを使ってみては」というありがたいコメントを頂いたので遅くなりましたが
ちょっと作ってみました。

ー ちょっと修正 ー

//
// signalhandler.hpp
//
#ifndef SIGSET_SIGNALHANDLER_HPP
#define SIGSET_SIGNALHANDLER_HPP 1

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>

class sighandler {
    typedef boost::function< void (const boost::system::error_code&, int) > sighandler_t;
public:
    enum mfs_quit { cancel, detach, join, force };

    sighandler(int sig, sighandler_t hdl, mfs_quit q = detach) : quit_(q), signal_number_(sig), 
        sigset_(io_service_, sig), handler_(hdl), signal_thread_(new boost::thread(boost::bind(&sighandler::invoke, this))) {}

    ~sighandler() {
        if( !signal_thread_->timed_join(boost::posix_time::seconds(0)) ) {
            if( quit_ == detach )
                signal_thread_->detach();
            else { 
                if( quit_ == cancel )
                    sigset_.cancel();
                if( quit_ == force )
                    raise(signal_number_);
                signal_thread_->join();
            }
        }
    }

private:
    void invoke() {
        sigset_.async_wait( handler_ );
        io_service_.run();
    }

    mfs_quit quit_;
    int signal_number_;             // Target signal number
    boost::asio::io_service io_service_;
    boost::asio::signal_set sigset_;
    sighandler_t handler_;          // Handler to invoke as signal handler
    boost::shared_ptr<boost::thread> signal_thread_;    // Thread to wait for the signal
};

#endif // SIGSET_SIGNALHANDLER_HPP

前のよりもずいぶん綺麗になりました。
前のは問答無用でデタッチしてましたが今回は
mfs_quit:
cancel - シグナルを待つのを中断、error_codeがoperation_abortedになってハンドラは実行される
detach - スレッドをデタッチ
join - joinできるまでひたすら待つ
force - raiseで強制的にシグナルを自分自身に送信してハンドラ実行
な感じです。

あとsignal_setのaddが使えるようにメンバー関数作るといいですね。