threadクラスの実装。その2-intrusive_ptrを使う-
出来るだけdeleteは書きたくないので、前回実装したintrusive_ptrを使って修正します。
修正する項目は
- thread_data_baseクラスのデストラクタをprotectedにする
- thread_data_baseクラスに参照カウンタを追加。
- thread_data_baseクラスにintrusive_ptr_add_ref( thread_data_base* )、intrusive_ptr_release( thread_data_base* )を追加
- threadクラスのthread_data_base*をintrusive_ptr< thread_data_base >に変更し、deleteを消去
の4点です。
class thread_data_base { /*略*/ protected: virtual ~thread_data_base(){ close(); } private: int ref_count; friend void intrusive_ptr_add_ref( thread_data_base* p ) { p->ref_count ++; } friend void intrusive_ptr_release( thread_data_base* p ) { p->ref_count --; if( p->ref_count <= 0 ) delete p; } };
class thread { typedef intrusive_ptr< thread_data_base > thread_data_ptr; /*略*/ ~thread() { } /*略*/ private: thread_data_ptr data; };
以上で完了です。使い方に変更はありません。
threadはnewして良いのか?
任意のタイミングでthreadを開始したい場合、boostにもstartメソッドが無い(privateなthread_startはある)ので、newすることになると思うのですが、google先生に聞いても、threadをnewする記述があまり見つからない。
何かまずいのだろうか?
eventを使うべき?
特に問題なければ、thread自体もintrusive_ptrでnewしようかと。
class thread { typedef intrusive_ptr< thread_data_base > thread_data_ptr; public: thread() : ref_count( 0 ) , data( nullptr ) { } template < typename Func > explicit thread( Func f ) : ref_count( 0 ) , data( new thread_data< Func >( f ) ) { data->start(); } private://デストラクタはprivateにする ~thread() { } public: //スレッドの終了を待機する。 void join() { if( data )data->wait(); } private: int ref_count; thread_data_ptr data; //non-copyable private: thread( const thread& ); thread& operator=( const thread& ); friend void intrusive_ptr_add_ref( thread* p ) { p->ref_count ++; } friend void intrusive_ptr_release( thread* p ) { p->ref_count --; if( p->ref_count <= 0 ) delete p; } }; typedef intrusive_ptr< thread > thread_ptr;
使い方
void hoge(){ std::cout << "hoge" << std::endl; } struct piyo { void operator()(){ std::cout << "piyo" << std::endl; } }; int main() { try { piyo p; thread_ptr t1 = new thread( &hoge ); thread_ptr t2 = new thread( p ); t1->join(); t2->join(); }//←ここでdeleteされる catch( std::exception& e ) { std::cout << e.what() << std::endl; } return 0; }
サンプル
- thread_02.zip
- VC++2008EE用