Для простоты предположим, что у нас есть только одна условная переменная, чтобы соответствовать одному условию, которое отражается логическим.Использование std :: conditional_variable для ожидания при условии
1) Почему std::condition_variable::wait(...)
снова блокирует мьютексы после того, как «уведомление» было отправлено, чтобы не спать?
2) Наблюдение за поведением в «1)», то это значит, что когда вы делаете std::condition_variable::notify_all
это только делает это так, чтобы все ожидающие потоки разблокирован/проснувшись ... но в порядке вместо всех однажды? Если да, то что можно сделать, чтобы сделать все сразу?
3) Если я беспокоюсь о спящем потоке только до тех пор, пока не будет выполнено условие, и не нужно ни одного бита для получения каких-либо мьютексов, что я могу сделать? Есть ли альтернатива или должен быть взломан текущий подход std::condition_variable::wait(...)
?
Если «повозка, запряженная волами» будет использоваться, будет эта работа для разблокировки все ожидающих потоков на состояние и может быть вызвана из любой (в потоке) нитей:
//declared somehwere and modified before sending "notify"(ies)
std::atomic<bool> global_shared_condition_atomic_bool;
//the single(for simplicity in our case) condition variable matched with the above boolean result
std::condition_variable global_shared_condition_variable;
static void MyClass:wait()
{
std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex);
while (!global_shared_condition_atomic_bool) global_shared_condition_variable.wait(lock);
}
это будет иметь был вызван из случайных "ожидания" нити так:
void random_thread_run()
{
while(someLoopControlValue)
{
//random code...
MyClass:wait(); //wait for whatever condition the class+method is for.
//more random code...
}
}
Edit:
ворота класс
#ifndef Gate_Header
#define Gate_Header
#include <mutex>
#include <condition_variable>
class Gate
{
public:
Gate()
{
gate_open = false;
}
void open()
{
m.lock();
gate_open = true;
m.unlock();
cv.notify_all();
}
void wait()
{
std::unique_lock<std::mutex> lock(m);
while (!gate_open) cv.wait(lock);
}
void close()
{
m.lock();
gate_open = false;
m.unlock();
}
private:
std::mutex m;
std::condition_variable cv;
bool gate_open;
};
#endif
# 1 Так что мьютекс предназначен исключительно для защиты доступа к самому 'std :: condition_variable'? # 2 Поэтому мне всегда приходится приобретать мьютекс из сигнальных потоков, прежде чем устанавливать условие boolean (которое теперь не должно быть атомарным) И отправка события уведомления, чтобы гарантировать, что уведомление проходит в целом? # 3 Могу ли я сохранить версию while (! BoolVar)? Я не понял, почему мне нужно использовать более сложную форму с двумя аргументами, извините. –
@JustinBieber Это потому, что вы певец, а не программист. Форма 2-arg проста и эквивалентна; без контроля потока, просто тестовая функция. Мьютекс защищает доступ к переменной условия * и * тестируемому значению. Существует узкое условие гонки, в котором не существует мьютекса в любой точке между настройкой bool и отправкой уведомления, при котором потоки, начинающие ждать, никогда не проснутся. – Yakk
Не могли бы вы взглянуть на класс, который я написал как сообщение, и подтвердить, что он безопасен в использовании? Мне очень жаль перетаскивать это, но мне тяжело обертывать вокруг себя голову. Это тяжело для нас, певцов. –