簡體   English   中英

正確使用std :: promise和std :: future,segfaults

[英]Proper usage of std::promise and std::future, segfaults

我一直在嘗試小型線程池實現的運氣。 但是,在概念化和實施之后,我遇到了麻煩。 我已經確認工作線程可以正常啟動和睡眠,也可以正確執行存儲的任務。 但是,我的程序存在段錯誤-我很確定它位於promise.set_value

我不確定我如何提供一個完整的,可驗證的示例(假設我幾乎無法上傳整個代碼),但是我將包括我認為與該問題有關的部分。 首先,工人是這樣創建的:

worker = [this](){
    while(true)
    {
        std::unique_lock<std::mutex> lock(mStatusMutex); //CV for status updates
        mCV.wait(lock);
        if(mStatus != Running) //If threadpool status does not imply running
            break; //Break out of loop, ending thread in the process
        else //If threadpool is in running state
        {
            lock.unlock(); //Unlock state
            while(true) //Loop until no tasks are left
            {
                mTasksMutex.lock(); //Lock task queue
                if(mTasks.empty()) //IF no tasks left, break out of loop and return to waiting
                {
                    mTasksMutex.unlock();
                    break;
                }
                else //Else, retrieve a task, unlock the task queue and execute the task
                {
                    std::function<void()> task = mTasks.front();
                    mTasks.pop();
                    mTasksMutex.unlock();
                    task(); //Execute task
                }
            }
        }
    }
};

然后啟動並存儲到std::vector<std::thread>如下所示:

std::thread tWorker(worker);
mWorkers.push_back(std::move(tWorker));

現在,我認為最棘手的部分是在任務隊列中添加/執行任務時,這是std::queue<std::function<void()>> 這里有以下兩個功能:

template<typename RT>
inline std::future<RT> queueTask(std::function<RT()> _task, bool _execute = false)
{
    std::promise<RT> promise;
    std::function<void()> func([&_task, &promise]() -> RT {
        RT val = _task();
        promise.set_value(val);
    });

    mTasksMutex.lock();
    mTasks.emplace(func);
    mTasksMutex.unlock();
    if(_execute) flush();
    return promise.get_future();
}
inline void flush()
{
    mCV.notify_all();
}

這種方法有什么原則上的錯誤嗎? 對於任何認為這是一個壞問題的人,請隨時告訴我如何改進它。 完整的代碼托管在我的github存儲庫中

主要問題是諾言已經失效。 queueTask完成時, promise被破壞,並且該任務現在只有一個懸掛的引用。 任務必須共享promise所有權,以使promise生存足夠長的時間來履行promise

底層的std::function對象_task ,因為您是通過引用捕獲它的。

您正在使用std::function ,它需要可復制的對象,因此... shared_ptr

template<typename RT>
inline std::future<RT> queueTask(std::function<RT()> _task, bool _execute = false)
{
    auto promise = std::make_shared<std::promise<RT>>();
    std::function<void()> func([promise, task=std::move(_task)]{
        RT val = _task();
        promise->set_value(val);
    });

    {
        std::lock_guard<std::mutex> lk(mTasksMutex); // NB: no manual lock()/unlock()!!
        mTasks.emplace(func);
    }
    if(_execute) flush();
    return promise->get_future();
}

考慮改為使用std::packaged_task

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM