2017-03-10 16 views
2

私はC++とboost :: thread_groupでスレッドプールを処理していますが、スレッド内でメソッド 'widgetProcessorJob'を呼び出してnullパラメータ(ウィジェット)を取得します。 私はさまざまな方法でそれを作ろうとしましたが、私はboost :: asioをひどく使っていると思います... 私は何が間違っているのかを教えてくれる誰かを探しています。boost :: thread_groupで呼び出されたメンバ関数のパラメータとして指定されたポインタがNULLです

void MarketingAutomation::processOnWidgets() { 
    boost::asio::io_service ioService; 
    boost::thread_group threadpool; 
    bool available = true; // need infinite loop in my program 
    int offset = 0; // Only for batching 

    boost::asio::io_service::work work(ioService); 
    for (int i = 0; i < _poolSize; i++) { 
     threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService)); 
    } 

    while (available) { 
     std::shared_ptr<sql::ResultSet> widgets(MyDBConnector::getInstance().getWidgets(_batchSize, offset)); // just getting some data from sql base with mysqlcppconn 

     if (!widgets->next()) { 
      offset = 0; 
      Logger::getInstance().logSTD("Restart widgets iteration !"); // this part is called when i did stuff on all batches 
     } else { 

      Logger::getInstance().logSTD("Proccess on " + std::to_string((offset/_batchSize) + 1) + " batch"); 

      // loop through the batch 
      while (!widgets->isAfterLast()) { 
       ioService.post(boost::bind(&MarketingAutomation::widgetProcessorJob, this, widgets)); 
       widgets->next(); 
      } 

      threadpool.join_all(); 
      Logger::getInstance().logSTD("Finish on " + std::to_string((offset/_batchSize) + 1) + " batch"); 
      offset += _batchSize; 

     } 
    } 
} 

// Here is the function called in thread 
void MarketingAutomation::widgetProcessorJob(std::shared_ptr<sql::ResultSet> widget) { 
    WidgetProcessor widgetProcessor(widget, _kind); // Here widget is already null, but why ? :'(
    widgetProcessor.processOnWidget(); 
} 

答えて

1
// loop through the batch 
while (!widgets->isAfterLast()) { 
    ioService.post(boost::bind(&MarketingAutomation::widgetProcessorJob, this, widgets)); 
    widgets->next(); 
} 

は、あなただけの1 std::shared_ptr<sql::ResultSet> widgets持っています。複数回ポストすることで、スマートポインタのコピーを作成していますが、これらのスマートポインタはすべて、同じ基礎となるsql::ResultSetを指しています。 これは、next()に電話をかけたときに、あなたがすべてのハンドラに投稿したのと同じレコードセットを「ネックス」していることを意味します。

スレッドの実行タイミングとさまざまな競合状態によっては、ハンドラが呼び出される前にレコードセットの最後に達している可能性があります。そうでない場合でも、競合状態にあります。最高でも、あなたが望むものの一部だけを得るでしょう。

+0

こんにちはのDraxおかげで、あなたの返信のためにたくさん、あなたは幸いにも、奇妙な行動にプログラムを駆動しますが可能性がミスを指して、私はこの結果セットに書いたことはありません!しかし、私は最終的に何が間違っているかを見つけ、数時間または数分で正解を投稿します。 –

1

私はboost :: asioをひどく使っていると思ったように!投稿後、無限ループなしでプログラムを試してみました。stopメソッドを呼び出さなかったので、ioServiceで動作するジョブは無限ループになりました。正しい答えを得るために、私はthread_pool & io_service宣言/定義を 'available'ループに移動し、各繰り返しでstopを呼び出しました!ここで@Draxの解答を含む正しい答えは次のとおりです。

void MarketingAutomation::processOnWidgets() { 
    bool available = true; 
    int offset = 0; 


    while (available) { 
     std::shared_ptr<sql::ResultSet> widgets(SlaaskDBConnector::getInstance().getWidgets(_batchSize, offset)); 

     if (!widgets->next()) { 
      offset = 0; 
      Logger::getInstance().logSTD("Restart widgets iteration !"); 
     } else { 

      boost::asio::io_service ioService; 
      boost::thread_group threadpool; 

      boost::asio::io_service::work work(ioService); 
      for (int i = 0; i < _poolSize; i++) { 
       threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService)); 
     } 

      Logger::getInstance().logSTD("Proccess on " + std::to_string((offset/_batchSize) + 1) + " batch"); 

      while (!widgets->isAfterLast()) { 
       ioService.post(boost::bind(&MarketingAutomation::widgetProcessorJob, this, widgets->getInt("id"))); 
       widgets->next(); 
     } 

      ioService.stop(); 
      threadpool.join_all(); 
      Logger::getInstance().logSTD("Finish on " + std::to_string((offset/_batchSize) + 1) + " batch"); 
      offset += _batchSize; 

     } 
    } 
} 

void MarketingAutomation::widgetProcessorJob(int widgetID) { 
    WidgetProcessor widgetProcessor(widgetID, _kind); // Here widget is already null, but why ? :'(
    widgetProcessor.processOnWidget(); 
} 
関連する問題