Single Threaded Execution
同時に実行できるスレッドを1つだけにするパターン。
boost::mutex と boost::mutex::scoped_lock を使えばいい。
以下は増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編のサンプルを Boost.Thread を使って書いたコード。
main.cpp
#include <boost/shared_ptr.hpp> #include <boost/thread.hpp> #include <boost/bind.hpp> #include "gate.h" #include "user_thread.h" namespace mtdp { namespace single_threaded_execution { void main() { boost::shared_ptr<gate> g(new gate()); boost::thread_group group; group.create_thread(boost::bind(&user_thread::run, boost::shared_ptr<user_thread>(new user_thread(g, "Alice", "Alaska")))); group.create_thread(boost::bind(&user_thread::run, boost::shared_ptr<user_thread>(new user_thread(g, "Bobby", "Brazil")))); group.create_thread(boost::bind(&user_thread::run, boost::shared_ptr<user_thread>(new user_thread(g, "Chris", "Canada")))); group.join_all(); } }}
gate.h
#ifndef MTDP_SINGLE_THREADED_EXECUTION_GATE_H_INCLUDED #define MTDP_SINGLE_THREADED_EXECUTION_GATE_H_INCLUDED #include <string> #include <iostream> #include "../thread_helper.h" namespace mtdp{ namespace single_threaded_execution { class bad_gate { private: int counter_; std::string name_; std::string address_; public: bad_gate() : counter_(0), name_("Nobody"), address_("Nowhere") { } void pass(std::string name, std::string address) { counter_++; name_ = name; address_ = address; check(); } std::string to_string() { return "No." + mtdp::to_string(counter_) + ": " + name_ + ", " + address_; } private: void check() { if (name_[0] != address_[0]) { thread_helper::shared_cout("***** BROKEN ***** " + to_string() + "\n"); } } }; class good_gate { private: int counter_; std::string name_; std::string address_; boost::mutex mutex_; public: good_gate() : counter_(0), name_("Nobody"), address_("Nowhere") { } void pass(std::string name, std::string address) { boost::mutex::scoped_lock lock(mutex_); counter_++; name_ = name; address_ = address; check(); } std::string to_string() { return "No." + mtdp::to_string(counter_) + ": " + name_ + ", " + address_; } private: void check() { if (name_[0] != address_[0]) { thread_helper::shared_cout("***** BROKEN ***** " + to_string() + "\n"); } } }; // これを変更して bad_gate と good_gate を切り替える typedef good_gate gate; }} #endif // MTDP_SINGLE_THREADED_EXECUTION_GATE_H_INCLUDED
user_thread.h
#ifndef MTDP_SINGLE_THREADED_EXECUTION_USER_THREAD_H_INCLUDED #define MTDP_SINGLE_THREADED_EXECUTION_USER_THREAD_H_INCLUDED #include <boost/shared_ptr.hpp> #include "gate.h" #include "../thread_helper.h" namespace mtdp{ namespace single_threaded_execution { class user_thread { private: boost::shared_ptr<gate> gate_; std::string myname_; std::string myaddress_; public: user_thread(boost::shared_ptr<gate> g, std::string myname, std::string myaddress) { gate_ = g; myname_ = myname; myaddress_ = myaddress; } void run() { thread_helper::shared_cout(myname_ + " BEGIN\n"); while (true) { gate_->pass(myname_, myaddress_); } } }; }} #endif // MTDP_SINGLE_THREADED_EXECUTION_USER_THREAD_H_INCLUDED