これを Boost.Asio を使ってかっこ良くしたいけどどうなんでしょうか。 URL |
Boost によるデザインパターン - Worker Thread
とのことだったので書いてみました。
#include <boost/asio.hpp> #include <boost/thread.hpp> #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> class thread_pool { boost::asio::io_service& io_service_; boost::shared_ptr<boost::asio::io_service::work> work_; boost::thread_group group_; public: thread_pool(boost::asio::io_service& io_service, std::size_t size) : io_service_(io_service) { work_.reset(new boost::asio::io_service::work(io_service_)); for (std::size_t i = 0; i < size; ++i) { group_.create_thread(boost::bind(&boost::asio::io_service::run, &io_service_)); } } ~thread_pool() { work_.reset(); group_.join_all(); } template <class F> void post(F f) { io_service_.post(f); } }; // test #include <iostream> #include <string> #include <boost/format.hpp> boost::mutex g_mutex; void func(const std::string& str, int num, int count) { int n = 0; for (int i = 0; i < num; i++) { n += count; { boost::mutex::scoped_lock lock(g_mutex); std::cout << (boost::format("%1% %2%/%3% (%4%)") % str % i % num % ::GetCurrentThreadId()) << std::endl; } ::Sleep(1000); } { boost::mutex::scoped_lock lock(g_mutex); std::cout << (boost::format("%1% %2%/%2% (%3%) result: %4%") % str % num % ::GetCurrentThreadId() % n) << std::endl; } } class hoge { private: int num_; int count_; public: hoge(int num, int count) : num_(num), count_(count) { } void func(const std::string& str) { ::func(str, num_, count_); } }; int main() { boost::asio::io_service io_service; thread_pool tp(io_service, 3); tp.post(boost::bind(func, "request1:", 5, 10)); tp.post(boost::bind(func, "request2:", 5, 10)); ::Sleep(3000); hoge h(3, 5); tp.post(boost::bind(&hoge::func, &h, "request3:")); tp.post(boost::bind(&hoge::func, &h, "request4:")); ::Sleep(7000); }
実行結果:
request1: 0/5 (3948) request2: 0/5 (3312) request1: 1/5 (3948) request2: 1/5 (3312) request1: 2/5 (3948) request2: 2/5 (3312) request3: 0/3 (264) // スレッドプールの空きがないので request4 は開始しない request1: 3/5 (3948) request2: 3/5 (3312) request3: 1/3 (264) request1: 4/5 (3948) request2: 4/5 (3312) request3: 2/3 (264) request1: 5/5 (3948) result: 50 request2: 5/5 (3312) result: 50 request4: 0/3 (3948) // スレッドプールの空きが出来たので request4 が開始された request3: 3/3 (264) result: 15 request4: 1/3 (3948) request4: 2/3 (3948) request4: 3/3 (3948) result: 15
キューの管理をboost::asio::io_serviceに任せることができて楽チンですね。
追記:
io_service::workがないと、キューが空になった時点でrun()が終わってしまうようです。
全ての処理が行われてくれないと困りますね・・・。workを追加しました。
修正履歴:
2011/04/08 17:16 : workを使ってなかったので修正。