作为boost :: thread_group中调用的成员函数的参数给出的指针为null

时间:2017-03-10 09:52:52

标签: c++ boost threadpool

我正在使用带有C ++和boost :: thread_group的线程池,但在线程中调用方法'widgetProcessorJob'获取一个空参数(小部件)。 我尝试以不同的方式制作它,我认为我正在使用boost :: asio严重... 我正在寻找一个可以告诉我我做错了什么以及哪种方式最好的方法?

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

2 个答案:

答案 0 :(得分:1)

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

您只有一个std::shared_ptr<sql::ResultSet> widgets。通过多次发布它来制作智能指针的副本,但所有这些智能指针都指向相同的基础sql::ResultSet。 这意味着当你致电next()时,你正在&#34; nexting&#34;您发布给所有处理程序的记录集。

现在,根据线程的执行时间和不同的竞争条件,你甚至可以在任何处理程序被调用之前到达记录集的末尾,即使不是这种情况,你也处于竞争条件会让你充其量只是你想要的一部分。

答案 1 :(得分:1)

正如我以为我使用了boost :: asio!发布后我尝试了我的程序,没有无限循环'可用',并且使用ioService运行的作业进行了无限循环,因为我从未调用过stop方法。为了得到正确答案,我移动了thread_pool&amp; 'available'循环中的io_service声明/定义,并在每次迭代时调用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();
}