Я пытаюсь перенести некоторый код Windows в Linux, в идеале через независимые от платформы библиотеки (например, boost), однако я не уверен, как перенести этот фрагмент кода события.
Часть кода включает два потока (давайте назовем их A и B). A хочет сделать что-то, что может сделать только B, поэтому он отправляет B сообщение, а затем ждет, пока B скажет, что все готово. В винде это выглядит примерно так:
Я посмотрел на библиотеку boost::thread, но, похоже, в ней не было ничего, что делало бы это, замыкания, которые я мог видеть, были boost::condition_variable, но, похоже, это означает в сочетании с мьютексом, что не так. здесь.
Я думаю, что ваш специфичный для Windows код использует мьютекс под капотом. Он просто абстрагируется от этого. rmeador 05.11.2009
возможный дубликат события ручного сброса Windows, похожего на pthread jww 11.02.2014
этот вопрос также содержит полезную информацию Loomchild 17.01.2017
Вероятно, нужно сделать еще немного, чтобы это полностью заработало, поскольку я не знаком с семантикой WaitForSingleObject (что произойдет, если два потока вызовут его одновременно, что произойдет, если один и тот же поток вызовет его дважды). Однако решение будет выглядеть очень похоже на это.
Ответ 3 · рейтинг 8 · oofafu
Вы можете использовать обещание и будущее из потока повышения:
#include <boost\thread.hpp>
boost::promise<bool> prom;
void foo()
{
auto future = prom.get_future();
auto result = future.wait_for(boost::chrono::milliseconds(1000));
// we get here if (a) 1 second passes or (b) bar sets the promise value
if (result==boost::future_status::ready)
{
/* bar set the promise value */
}
if (result==boost::future_status::timeout)
{
/* 1 second passed without bar setting promise value */
}
}
void bar()
{
prom.set_value(true);
}
Ответ 4 · рейтинг 4 · Masood Khaari
Поскольку комментарии для меня закрыты, мне пришлось разместить свои комментарии к предыдущим постам в качестве ответа. Но на самом деле я не отвечаю.
1) Проблема с решением @Alan. Предоставленный им пример кода работает хорошо. Но это отличается от функций Windows Events. Когда объект события Windows установлен, немедленно возвращается любое количество последующих вызовов WaitForSingleObject, показывая, что объект находится в сигнальном состоянии. Но с решением boost mutex/conditionbar() должен уведомлять об условии для каждого foo() вызова, который в этом нуждается. Это значительно усложняет ситуацию для "кросс-платформенных" функций Windows Event. notify_all() тоже не может помочь.
Конечно, это каким-то образом решается в примере кода @deft_code с помощью логической переменной. (Хотя он сам страдает от проблемы состояния гонки. Подумайте, если SetEvent(...) называется мертвым после while(!evt->m_bool) и до evt->m_cond.wait(lock) из отдельного потока. Возникнет взаимоблокировка. Однако это можно решить, используя некоторые методы управления состоянием гонки, чтобы сделать два оператора while() и wait() atomic.) Но у него есть свой недостаток:
2) Также есть проблема с кодом @deft_code при использовании комбинации boost mutex/condition/bool:
Объекты событий в Windows могут иметь имя, что позволяет использовать их для межпроцессной синхронизации. Например, процесс А может создать именованное событие и установить его следующим образом: SetEvent(hFileIsReady). После этого независимо от количества процессов, ожидающих установки этого события (таким образом вызывая WaitForSingleObject(hFileIsReady)), немедленно продолжит свое обычное выполнение до тех пор, пока событие не будет снова сброшено в процессе A ResetEvent(hFileIsReady).
Но комбинация mutex/condition/bool не может позволить себе такой функционал. Конечно, мы можем использовать boost named_condition и named_mutex. Однако как насчет логической переменной, которую мы должны проверить перед ожиданием?
Ответ 5 · рейтинг 3 · Mahmoud Al-Qudsi
Для всех, кто участвует или работает над переносом многопоточного собственного кода Windows C/C++ на Linux/Mac, мы создали библиотеку с открытым исходным кодом (под лицензией MIT), которая реализует как ручной, так и автоматический сброс событий WIN32 поверх pthreads, включая полную реализацию WaitForSingleObject и WaitForMultipleObjects, что делает его единственным известным мне портом WFMO, доступным на Linux/Mac.
pevents доступен на GitHub, прошел боевые испытания и используется некоторыми громкими именами; также где-то плавает буст-порт певентов.
Использование pevents значительно упростит перенос кода из Windows, поскольку лежащие в основе парадигмы сильно различаются между платформами Windows и posix, хотя я бы рекомендовал всем, кто пишет многоплатформенный код, использовать существующую кроссплатформенную библиотеку многопоточности, такую как boost, в первую очередь.
Я сделал (или видел) все следующее в разное время для таких вещей:
Используйте мьютекс + переменную условия.
Используйте канал, заставив foo создать канал и передать его конец для записи в bar. Bar затем записывает в трубу, когда bar готов. (Это даже работает с несколькими процессами).
Задайте foo poll для логического значения (да, это плохая идея).
Ответ 8 · bua
Похоже, Вы ищете сигнально-щелевой механизм. Вы можете найти его в:
Классы condition_variable и condition_variable_any предоставляют механизм, позволяющий одному потоку ожидать уведомления от другого потока о том, что определенное условие стало истинным.
Ответ 10 · рейтинг -1 · Elmar Weber
В системах, совместимых с Posix, вы можете использовать Posix IPC. Он используется для обмена сообщениями между процессами и потоками. Если я правильно помню, есть доступный порт cygwin.