もしもBoost.Threadにinterruptが無かったら。
VC限定なコードですけが、こんな感じで追加できるんじゃないかと。
元ネタはtwitterでid:melponさんがstd::threadにinterruptが無いので欲しいってとこからです。
id:melponさんがつぶやいてたコードの大部分借りました。
#include "stdafx.h" #include <iostream> #pragma warning(push) #pragma warning(disable: 4819) #include <boost/thread.hpp> #include <boost/bind.hpp> #include <boost/scoped_ptr.hpp> #pragma warning(pop) namespace thread { namespace cancellation { class interrupted_exception {}; class interruptible_thread; template <class F> void thread_proxy(interruptible_thread* p, F f); class interruptible_thread { __declspec(thread) struct tls { interruptible_thread* this_thread; }; public: // publicなのは手抜きです。すみません。 static __declspec(thread) tls thread_info; private: boost::scoped_ptr<boost::thread> th; mutable boost::mutex mutex; bool interrupted_; public: template <class F> explicit interruptible_thread(F f) : th() , mutex() , interrupted_(false) { // threadの開始thread化したい関数fは // detail::thread_proxy<F>でcallする th.reset( new boost::thread( boost::bind(&detail::thread_proxy<F>, this, f))); } void join() { th->join(); } // boost::threadへの転送関数を定義 void interrupt() { boost::unique_lock<boost::mutex> lock(mutex); interrupted_ = true; } bool interrupted() const { boost::unique_lock<boost::mutex> lock(mutex); return interrupted_; } }; interruptible_thread::tls interruptible_thread::thread_info; namespace detail { template <class F> void thread_proxy(interruptible_thread* p, F f) { interruptible_thread::thread_info.this_thread = p; // thread-local try { f(); } catch (interrupted_exception&) {} } } // namecpace detail } // namecpace cancellation } // namecpace thread // ここからテスト用のコード void worker_thread() { namespace tc = thread::cancellation; while(1) { if (tc::interruptible_thread::thread_info.this_thread->interrupted()) { throw tc::interrupted_exception(); } } } int _tmain(int argc, _TCHAR* argv[]) { namespace tc = thread::cancellation; tc::interruptible_thread t0(&worker_thread); tc::interruptible_thread t1(&worker_thread); t0.interrupt(); t0.join(); t1.interrupt(); t1.join(); std::cout << "cancel" << std::endl; return 0; }
C++0xではthread_localキーワードが追加されるので
TlsAlloc(Windows) pthread_key_create(POSIX)とか環境依存なコードは書かなくても済みそうです
でも作るのは面倒なので最初から付けてください・・・。
ちなみにg++では
__declspec(thread) struct tls { interruptible_thread* this_thread; }; public: // publicなのは手抜きです。すみません。 static __declspec(thread) tls thread_info;
な部分はどう書けば良いんですかね。
struct tls { interruptible_thread* this_thread; }; public: // publicなのは手抜きです。すみません。 static __thread tls thread_info;