Я новичок в потоках C ++, и я пытаюсь написать диспетчер задач с циклическим циклом (кооператив), используя потоки C ++. Действительно ли объявление round_robin_task_ulock ниже допустимо — это глобальная статическая переменная. Я хочу отложить блокировку мьютекса, пока не запустится поток менеджера задач.
static std::mutex round_robin_task_mutex;
static std::condition_variable task_manager_cvar;
static thread round_robin_task_manager_thread;
static std::unique_lock<std::mutex>
round_robin_task_ulock(round_robin_task_mutex, std::defer_lock);
static void round_robin_task_manager()
{
round_robin_task_ulock.lock();
//..
}
После запуска потока диспетчера задач он может запустить задачу циклического перебора с уведомлением и последующим ожиданием.
round_robin_tasks[current_task_id].task_cvar.notify_one();
// release the mutex and go to sleep
task_manager_cvar.wait(round_robin_task_ulock);
// now we own the mutex again
и когда задача циклического перебора хочет приостановить себя, она уведомляет поток диспетчера задач
task_manager_cvar.notify_one();
round_robin_tasks[current_task_id].task_cvar.wait
(round_robin_task_ulock, [] { return
round_robin_tasks[my_task_id].task_running_now; } );
Есть ли очевидные проблемы с этим? Я читал о ложных следах. Возможно ли, что ложное пробуждение может разбудить поток диспетчера задач, пока задача круглого робота все еще владеет мьютексом, или гарантируется, что при возврате функции ожидания мьютекс всегда принадлежит (заблокирован) потоку, вызвавшему ожидание.
Вы должны построить свой код так, чтобы без какой-либо условной переменной он все еще работал. Если он будет работать, если он заблокировал мьютекс, проверил условие, разблокировал мьютекс и сразу повторил цикл, тогда он будет работать с условной переменной, только более эффективно.
Реализация мог включайте переменные состояния каждые 10 миллисекунд, если это необходимо по какой-либо причине, или если было какое-то странное взаимодействие с такими инструкциями, как MWAIT, строки кэша и транзакционные блокировки, или какой-то другой странной аппаратной функцией.
Кажется, я вспоминаю чтение об архитектуре, которая будет сигнализировать о событиях ожидания в ячейках памяти всякий раз, когда записывается какая-либо часть этой строки кэша. И библиотека потоков не дополнила структуру до размера строки кэша.
Так ДА вам, возможно, придется обрабатывать сотни пробуждений в секунду, и ваш код все равно должен работать правильно.
Из того, что я вижу из того, что вы написали, у вас есть только одно место, где вы проверяете сказуемое, что является условием, которое должно быть истинным, чтобы пройти через условие. И перед каждым уведомлением вы должны были обновить предикат. Предикат всегда должен записываться или считываться, будучи защищенным той же блокировкой, что и переменная условия.
Если вы хотите другое поведение, вы можете использовать семафор.
Других решений пока нет …