std::unique_lock не захватывает мьютекс

77
19 сентября 2021, 16:20

Разрабатываю имплементацию очереди задач. В классе содержатся следующие данные:

class TaskQueue
{
private:
    std::queue<BasicTaskPtr> m_queue;
    std::condition_variable  m_cv;
    std::mutex               m_mutex;
public:
    explicit TaskQueue()
        : m_queue()
        , m_cv()
        , m_mutex()
    {}
    BasicTaskPtr popTask();
    void pushTask(BasicTaskPtr task);
};

Реализации методов:

BasicTaskPtr TaskQueue::popTask()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    std::cout << "locked" << std::endl;
    // condition_variable может выдать ложное срабатывание,
    // поэтому устанавливаем предикат окончания ожидание 
    m_cv.wait(lock, [&]()
        {
            return !this->m_queue.empty();
        });
    auto task = m_queue.front();
    m_queue.pop();
    std::cout << "unlocked" << std::endl;
    return task;
}
void TaskQueue::pushTask(BasicTaskPtr task)
{
    std::unique_lock<std::mutex> lock(m_mutex);
    if (m_queue.size() <= Constants::kMaxTaskQueueSize)
    {
        m_queue.push(task);
        m_cv.notify_one();
    }
}

Поток исполнитель выглядит следующим образом:

void Executor(TaskQueue& queue)
{
    while (true)
    {
        queue.popTask()->execute();
    }
}

Поток генератор выглядит следующим образом: class TestTask : public BasicTask { public:

TestTask(const std::string &str)
    : BasicTask(BasicTask::Json({ {"str", "qwerty_" + str} }))
{}
void execute() override
{
    std::cout << std::this_thread::get_id() << " - " << m_input["str"].get<std::string>() << std::endl;
}

};

void Producer(TaskQueue &queue)
{
    int i{ 0 };
    while (i++ < 60)
    {
        queue.pushTask(std::make_shared<TestTask>(TestTask(std::to_string(i))));
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

Создаю все вот так:

TaskQueue queue;
std::thread executor_thread_1(Executor, std::ref(queue));
std::thread executor_thread_2(Executor, std::ref(queue));
std::thread producer_thread(Producer, std::ref(queue));
producer_thread.join();

На что получаю следующий вывод: lockedlocked То есть получается, что мьютекс пропускает второй поток при том, что первый его все еще не разблокировал. Не понимаю что сделал не так

READ ALSO
Как из проекта Qt сделать библиотеку?

Как из проекта Qt сделать библиотеку?

подскажите пожалуйста, у меня есть проект на Qt с использованием qml-я, своеобразное приложение для работы с базой данныхВозникла необходимость...

113
Как составить граматику чтобы она заработала?

Как составить граматику чтобы она заработала?

Создаю граматику для вычисления выраженияИспользую Boost

115
Cделать правильный запрос SQL

Cделать правильный запрос SQL

Есть 2 таблицы products(id,product_name,price) и reviews(id,product_id,commentary)

109