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;
}

サンプル