2012-02-08 25 views
3

メンバーメソッドの1つのスレッドインスタンスを開始するクラスを作成しようとしています。 私がメインで行います。その後、std :: thread、 `this 'のスレッドを開始する(クラス自体の中から)

test myinstance; 
std::thread mythread(myinstance); 

物事がコンパイルします。しかし、以下の構成使用して:

#include <stdio.h> 
#include <unistd.h> 
#include <thread> 

class test 
{ 
     std::thread *pt; 
public: 
     test() 
     { 
       pt = new std::thread(this); 
     } 

     void operator()() const 
     { 
       printf("thread start\n"); 
       sleep(5); 
       printf("thread end\n"); 
     } 
}; 

int main(int arg, char *argv[]) 
{ 
     test ptest; 
     sleep(10); 

     return 0; 
} 

することは、私は次のエラーを取得する:

[email protected]:~$ g++ -std=c++0x test.cpp In file included from /usr/include/c++/4.6/thread:39:0, from test.cpp:3: /usr/include/c++/4.6/functional: In member function 'void std::_Bind_result<_Result, _Functor(_Bound_args ...)>::__call(std::tuple<_Args ...>&&, std::_Index_tuple<_Indexes ...>, typename std::_Bind_result<_Result, _Functor(_Bound_args ...)>::__enable_if_void<_Res>::type) [with _Res = void, _Args = {}, int ..._Indexes = {}, _Result = void, _Functor = test*, _Bound_args = {}, typename std::_Bind_result<_Result, _Functor(_Bound_args ...)>::__enable_if_void<_Res>::type = int]': /usr/include/c++/4.6/functional:1378:24: instantiated from 'std::_Bind_result<_Result, _Functor(_Bound_args ...)>::result_type std::_Bind_result<_Result, _Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {}, _Result = void, _Functor = test*, _Bound_args = {}, std::_Bind_result<_Result, _Functor(_Bound_args ...)>::result_type = void]' /usr/include/c++/4.6/thread:117:13: instantiated from 'void std::thread::_Impl<_Callable>::_M_run() [with _Callable = std::_Bind_result]' test.cpp:28:1: instantiated from here /usr/include/c++/4.6/functional:1287:4: error: '((std::_Bind_result*)this)->std::_Bind_result::_M_f' cannot be used as a function

だから私の推測では、それがこのように動作しないことです。 私の質問は今です:どのように私は、std :: threadを使って、クラスが独自のメソッドの1つのスレッドを開始させることができますか?

答えて

3

std::threadのコンストラクタの一つは次のようになります。

template<typename Callable> 
    explicit thread(Callable func); 

これはoperator()で呼び出すことができることを意味し、呼び出し可能ある何かを渡す必要があります。 std::threadに渡すものは呼び出し可能ではありません。

thisに電話をかけることはできません。 thisは現在のオブジェクトへのポインタであり、呼び出し可能ではありません。

std::threadコンストラクタには、メンバー関数やその他の関数を渡す必要があります。

また、ファンクタを作成し、それを呼び出し可能なように渡すこともできます。

EDIT:

test t; 
    std::thread my_thread(t); //invokes operator() on test. 

//also remove this statement from your ctor: pt = new std::thread(this); 
+6

'* this'を使用してください。 –

+0

ああ、ヨアキム・ピレボリが答えを出しました! 私が行う場合 pt = new std :: thread(* this); またはさらに pt =新しいstd :: thread(std :: ref(* this)); コンパイルして実行します! –

+2

@FolkertvanHeusden私は、同じクラスのオーバーロードされた 'operator()'を使っているときに、クラスのctor内でスレッドを開始するあなたの構成が奇妙であると言わなければなりません。 –

3

多くの修正:

#include <iostream> 
#include <thread> 

struct test 
{ 
    void operator()() const 
    { 
     std::cout << "thread start\n"; 
     sleep(5); 
     std::cout << "thread end\n"; 
    } 
}; 

int main(int arg, char *argv[]) 
{ 
    std::thread pt(std::move(test())); 

    pt.join(); 
    return 0; 
} 

修正

  • 関心事の分離ちょうどそれを呼び出すために、実際にoperator()をオーバーロードしている気づいた、あなたがfollwowingを行う必要があり(あなたはtestをスレッドなしで実行できます、よろしく!)
  • std :: threadインスタンス(メモリ+リソース)がリークする
  • スレッドが終了するのを(決定論的に)待たず、あなたが睡眠が長く続くことを知っていると思っても、これはUBです。
  • 移動を実行することでptestのローカル/コピーを避ける方法に注意してください。 は技術的には、std::moveが冗長ですが、私は具体的なものが好き、あなたがmost vexing parseに実行したい:

    std::thread pt((test())); 
    
+0

スレッドなしのテストについて:bool debugのようなコンストラクタにパラメータを追加してスレッドを開始せず、手動でworker-part(通常はスレッド内にある)を手動で呼び出すことができます。その方法で情報隠蔽が維持されます。 –

+0

downvoter明確にしてくださいできますか? – sehe

+0

@FolkertvanHeusden実行モデル情報はいつからですか?クラスがTaskManagerか何かであるかもしれません。現時点では、実行する場所を決めるのは論理的にはファンクタの責任ではなく、スレッドのどの機能を呼び出すかを決定する責任もありません。それは情報隠蔽ではなく、私の見解では無差別な情報共有です。 – sehe

0

これを試してみてください。

pt =新しいstd :: thread(std :: ref(* this));

+0

Ooops、申し訳ありませんが、私の答えは重複していました。 – BitTwiddler

関連する問題