在第二个线程中管理队列

时间:2018-08-20 16:37:29

标签: c++ multithreading c++11

我创建了一个线程,该线程负责对传递的数据进行一些长时间的操作。所有数据都放入主线程的队列中,然后第二个线程获取此数据,对其进行操作,然后返回到包含已执行数据ID和结果的映射。类看起来像这样:

#include <memory>
#include <future>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <condition_variable>
#include <iostream>
#include <sstream>

typedef unsigned int Key;

class DatabaseWorker
{
public:
    DatabaseWorker()
    {
        startThread();
    }

    ~DatabaseWorker()
    {
        stopThread();
    }

    void startThread()
    {
        std::cout << "starting thread" << std::endl;
        m_futureObj = m_exitSignal.get_future();
        m_thread = std::thread(&DatabaseWorker::work, this);
    }

    void stopThread()
    {
        std::cout << "stopping thread" << std::endl;
        m_exitSignal.set_value();
        if (m_thread.joinable())
            m_thread.join();
    }

    void work()
    {
        std::cout << "thread started" << std::endl;
        bool bEmpty;
        std::pair<Key, std::string> data;
        while (m_futureObj.wait_for(std::chrono::milliseconds(1)) == std::future_status::timeout)
        {
            //Check queue size
            {
                std::lock_guard<std::mutex> lock(m_mutex);
                bEmpty = m_requests.empty();
            }
            if (!bEmpty)
            {
                std::cout << "something in queue" << std::endl;
                //Get data from queue
                {
                    std::lock_guard<std::mutex> lock(m_mutex);
                    data = m_requests.front();
                    m_requests.pop();
                }

                Key id = data.first;
                std::string str = data.second;
                //HERE do some operation with string
                str += "_123";

                //Prepare result
                {
                    std::lock_guard<std::mutex> lock(m_mutex);
                    m_results.insert(std::make_pair(id, str));

                    //Inform conditional about data
                    m_conditionals.find(id)->second.second = true;
                    m_conditionals.find(id)->second.first->notify_one();
                }
            }
        }
    }

    Key addToQueue(const std::string &data)
    {
        std::cout << "adding to queue" << std::endl;
        std::lock_guard<std::mutex> lock(m_mutex);  //lock
        m_requests.push(std::make_pair(m_nID, data));   //adddata to queue
        m_conditionals.insert(std::make_pair(m_nID, std::make_pair(std::make_shared<std::condition_variable>(), bool(false))));
        return m_nID++;
    }

    std::string getResult(Key id)
    {
        std::cout << "getting result" << std::endl;
        std::unique_lock<std::mutex> lock(m_mutex);
        //Check if data ready
        m_conditionals.find(id)->second.first->wait(lock, [&](){
            return m_conditionals.find(id)->second.second;  //return bool data
        });

        //If data ready
        auto result = m_results.find(id)->second;   //Get data from thread
        //Delete data
        m_results.erase(m_results.find(id));    //HERE HEAP ISSUE OCCURS SOMETIMES!!!
        return result;
    }

private:
    std::queue<std::pair<Key, std::string>> m_requests;
    std::map<Key, std::string> m_results;
    std::map < Key, std::pair< std::shared_ptr<std::condition_variable>, bool>> m_conditionals;

    std::promise<void> m_exitSignal;
    std::future<void> m_futureObj;
    std::mutex m_mutex;
    std::thread m_thread;

    Key m_nID = 0;
};

然后在主函数中,我要添加一些数据并等待线程的响应:

int main()
{
    DatabaseWorker dbWorker;
    std::ostringstream stringStream;
    std::string data;
    std::vector<Key> keys;
    int i;
    for (i = 0; i < 100; i++)
    {
        stringStream.str("");
        stringStream << "data_" << i;
        data = stringStream.str();
        keys.push_back(dbWorker.addToQueue(data));
    }

    for each (Key key in keys)
    {
        std::cout << "key: " << key << " data: " << dbWorker.getResult(key) << std::endl;
    }
}

问题在于,有时在调用getResult()方法期间,我在m_results.erase(m_results.find(id))处遇到了内存错误:

Debug Assertion Failed!
Expression _pFirstBlock == pHead

我缺乏理解/实施的地方在哪里?

0 个答案:

没有答案