Разрешено ли компилятору переупорядочивать операторы вокруг `std::condition_variable::notify_one`?

Следующий код представляет собой структуру, которую я написал, чтобы позволить мне ставить работу в очередь для выполнения в нескольких рабочих потоках, и которая блокирует основной поток до тех пор, пока не станет доступен новый рабочий поток.

      struct WorkQueue{
    const std::size_t size;
    std::vector<uint8_t> threadActive;
    std::condition_variable cond;
    std::mutex mu;

    std::vector<std::jthread> threads;

    WorkQueue(std::size_t size_ = 1) :
        size{size_}
    {
        threads.resize(size);
        threadActive.resize(size);
        std::fill(std::begin(threadActive), std::end(threadActive), false);
    }

    template<typename Function>
    void enqueue(Function&& f){
        auto numActiveThreads = [&](){
            return std::count(std::begin(threadActive), std::end(threadActive), true);
        };
        auto availableThread = [&](){
            return std::find(std::begin(threadActive), std::end(threadActive), false) - std::begin(threadActive);
        };

        std::unique_lock<std::mutex> lock{mu};

        //wait until a thread becomes available
        if(numActiveThreads() == size){
            cond.wait(lock, [&](){ return numActiveThreads() != size; });
        }

        //get an available thread and mark it as active
        auto index = availableThread();
        threadActive[index] = true;

        //start the new thread and swap it into place
        std::jthread thread{[this, index, fn = std::forward<Function>(f)](){
            fn();
            threadActive[index] = false;
            cond.notify_one();
        }};
        threads[index].swap(thread);
    }
};

У меня есть два вопроса о коде лямбда-выражения, выполняемом jthread:

  1. Нужно ли блокировать мьютекс mu при настройке?

  2. Разрешено ли компилятору переупорядочивать код и выполнять cond.notify_one() перед установкой threadActive[index] = false?

Я думаю, что необходимо заблокировать мьютекс тогда и только тогда, когда компилятору разрешено изменять порядок операторов. Это правильно?

0 ответов

Другие вопросы по тегам