2017-12-05 2 views
1

、とstdで「タイプ」:: result_ofという名前の無いタイプすべての通信オーバーヘッドを処理するWorkerClientというクラスを介してこれを行います。grpc&いるProtobuf - エラー:<>私は、すべての労働者(grpc非同期サーバ)に作業を配布するマスタークラス(grpc非同期クライアントを)持っている私のプログラムで

私のマスタークラスは、サーバーからの応答を待つためにセットアップする(デタッチ)バックグラウンドスレッドをしよう、と私の困難が生じた場所です。

「AsyncComplete」関数をWorkerClientクラスの一部にしました(grpc.ioのAsync-Greeterチュートリアルに基づく非同期クライアント/サーバーgrpcに関する最近のプログラムのアプローチと同じです)このアプローチのクラスの詳細は以下のとおりです。ここで

class WorkerClient { 
     public: 
     WorkerClient(std::shared_ptr<grpc::Channel> channel); 

     void MapReduceWork(masterworker::WorkReq); 
     void AsyncComplete(void *, void *, int); 

     struct AsyncClientCall { 
      masterworker::WorkReply  reply; 
      grpc::ClientContext   context; 
      grpc::Status    status; 
std::unique_ptr<grpc::ClientAsyncResponseReader<masterworker::WorkReply>> rsp_reader; 
     }; 

     std::mutex           mtx; 
     std::unique_ptr<masterworker::MasterWorker::Stub> stub; 
     grpc::CompletionQueue        cq; 
     masterworker::WorkReq        work_req; 
     ClientState           state; 
    }; 

    class Master { 
      public: 
      Master(const MapReduceSpec&, const std::vector<FileShard>&); 
      ...... 
      private: 
      std::mutex      mtx; 
      std::vector<FileShard>   map_tasks; 
      std::vector<ReduceTask *>  reduce_tasks; 
      std::vector<WorkerClient *>  clients; 
      std::vector<std::string>  m_interm_files; 

      std::vector<FileShard>   shards; 
      MapReduceSpec     mr_config; 
     }; 

私は、関連する機能が

void WorkerClient::AsyncComplete(void *c, void *m, int client_num) 
{ 
    void   *got_tag = NULL; 
    bool   ok = false; 
    Master   *mast = static_cast<Master*>(m); 
    WorkerClient *client = static_cast<WorkerClient*>(c); 

    cq.Next(&got_tag, &ok); 
    if (ok == false) { 
     fprintf(stderr, "cq->Next false!\n"); 
     return; 
    } 
    ...... 
} 

スレッド

void Master::RunMapJob() 
{ 
     // clients[] is of type WorkerClient   
     ptr = new std::thread(&WorkerClient::AsyncComplete, 
       static_cast<void*>(clients[i]), static_cast<void*>(this), i); 
     ptr->detach(); 
    ...... 
} 

そして最後に、これまでのところ、問題自体

g++ -c master.cc -I../external/include -std=c++11 -g 
In file included from /usr/include/c++/4.8/mutex:42:0, 
       from master.h:3, 
       from master.cc:2: 
/usr/include/c++/4.8/functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (WorkerClient::*)(void*, void*, int)>(void*, void*, int)>’: 
/usr/include/c++/4.8/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (WorkerClient::*)(void*, void*, int); _Args = {void*, void*, int&}]’ 
master.cc:223:65: required from here 
/usr/include/c++/4.8/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (WorkerClient::*)(void*, void*, int)>(void*, void*, int)>’ 
     typedef typename result_of<_Callable(_Args...)>::type result_type; 
                  ^
/usr/include/c++/4.8/functional:1727:9: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (WorkerClient::*)(void*, void*, int)>(void*, void*, int)>’ 
     _M_invoke(_Index_tuple<_Indices...>) 
     ^
make: *** [master.o] Error 1 

を作成するための呼び出しを詳述しています明らかなものを排除したsは、std :: refを使ってスレッド関数に変数参照を渡すのではなく、一般的には正しいスレッド関数の引数を渡さないようにします。私はAsyncCompleteを静的なスタンドアロンの関数にしようとしましたが、cq.Next(WorkerClient-> cq.Next()に変更)の呼び出しがstd :: bad_alloc例外をスローしていたCompletionQueueコードが舞台裏で行われていることを理解することができます)。

それが助け場合、私は(下記)、コンパイル時に窒息しているようだ/usr/include/c++/4.8/functionalラインを見つけることができた

typedef typename result_of<_Callable(_Args...)>::type result_type; 

誰も私がなぜこの両方について説明することができますコンパイルに失敗していて、適切な修正がどのように見えるのでしょうか?私はここに質問を投稿するのが初めてで、フィードバックは大歓迎です。これは長いことを知っていますが、私はすべての情報を持っていることを確認したかったのです。

ありがとうございます。

[システムの詳細:のUbuntu 14.04、3.0 protobufs、protobufs 3.0のソースから構築grpc]

答えて

0

この行は問題である。

ptr = new std::thread(&WorkerClient::AsyncComplete, static_cast<void*>(clients[i]), static_cast<void*>(this), i)

std::threadのコンストラクタはファンクタとの引数を取りそれに。 WorkerClientのインスタンスを指定せずに&WorkerClient::AsyncCompleteを提供しています。私はクライアントが実際にはclients[i]に含まれていると思います。試してみると

ptr = new std::thread(std::bind(&WorkerClient::AsyncComplete, clients[i], static_cast<void*>(clients[i]), static_cast<void*>(this), i)) 

コンパイルする必要があります。

+0

あなたは人生の節約者です...ありがとう!私の以前のプログラムでは、同様のスレッド作成呼び出しを行っていましたが、実際にはバインド呼び出しはありませんでしたが、引き続き引数を渡しました。なぜスレッドctorがバインドを必要とするのか、他のスレッドは必要ないのでしょうか? -----たとえば、--------- スレッド。push_back(新しいstd :: thread(&Vclient :: AsyncComplete、vendors [i]、static_cast (this))); ------------ ここで 'threads'はstd :: threadポインタのベクトルであり、そのコードを含むプログラムは適切にコンパイルされて機能します。 – user3282129

+0

http://en.cppreference.com/w/cpp/thread/threadの 'std :: thread'文書の例を見ると、最初の引数はファンクタでなければならないことがわかります:' Function && f、Args && ... args'。メソッドのファンクタを作成するには、メソッドをそのクラスのインスタンスにバインドする必要があります。フリースタンディング関数または静的クラスメソッドの場合、バインドする必要はありません。 – jupp0r

関連する問題