2016-06-29 3 views
0

У меня есть два события, которые запускаются и обрабатываются двумя обработчиками событий. В EventHandler2 запущен boost::thread. В EventHandler2 приложение ожидает завершения этого потока, вызвав на нем join().Как подождать, пока нить присоединится, только если он был запущен

Это хорошо работает на быстрых компьютерах, потому что событие, начавшее поток, всегда запускалось первым, перед другим событием, которое вызвало приложение ait для join(). Однако на старых машинах события запускаются в другом порядке (потому что есть некоторые тяжелые вычисления, которые нужно выполнить до того, как вызывается EventHandler2). Так что EventHandler1 вызывается первым и не ждет, так как join() немедленно возвращается (нить еще не запущена, потому что 2-й случай не был запущен). Какое лучшее я могу здесь сделать? Мне нужно заблокировать мьютексы, а затем дождаться его, прежде чем я вызову join(). Таким образом, я уверен, что поток запускается до того, как на него вызывается join(). Каков наилучший образец для использования в этом случае? Спасибо!

+0

http://stackoverflow.com/questions/9094422/how-to-check-if-a-stdthread-is-still-running, длинный рассказ: используйте bool. – lorro

+0

'std :: atomic ' может быть тем, что вы ищете ... –

ответ

0

Кажется, вам нужно указать порядок или приоритет выполнения. Из вашего вопроса также кажется, что у вас гетерогенные потоки (с точки зрения поведения), поэтому я собираюсь предложить синхронизацию. A mutex, скорее всего, не будет достаточно (хотя во многих реализациях мьютекс совпадает с двоичным семафором). Простой способ сделать это - с мониторами. https://en.wikipedia.org/wiki/Monitor_(synchronization)

0

Чтобы перефразировать проблему (сообщите мне, если я неправильно понял): у вас есть два обработчика событий (A и B), которые будут выполнены, и не гарантировано, что каждый из них будет выполнен первым - порядок выполнения может быть (A, B), или он может быть (B, A) ... но в любом случае вы хотите, чтобы система вела , как если бы обработчики были выполнены в (A, B) порядке.

Способ, которым я подходил к этой проблеме, состоит в том, чтобы сделать обработчиков более умными, чтобы они могли обнаружить, когда обработчик «неправильный» был выполнен первым и обработал его изящно. В частности, когда ваш обработчик B выполняется, он должен иметь способ определить, уже выполнен ли обработчик A. Если B видит, что A уже выполнено, тогда B может сделать свою обычную вещь (т. Е. Join() поток), и все хорошо. С другой стороны, если B обнаруживает, что A еще не выполнил, тогда B вместо этого должен просто установить флаг (возможно, логическое в структуре данных, к которому A будет иметь доступ?), Так что, когда обработчик A будет работать позже, будет знать, что обработчик B уже был-и-ушел, и поэтому A будет знать, что он не может полагаться на B, чтобы выполнять любую работу по очистке. То есть, когда A запускается, он проверяет флаг; если флаг был установлен B, то A также будет вызывать join() перед возвратом, так как A знает, что B не будет делать это позже (или, альтернативно, возможно, A может планировать другое событие B, если вы предпочитаете не звонить join() непосредственно из обработчика A).

Если ваши обработчики A и B оба вызываются в одном и том же потоке, тогда это должно быть просто сделать; если A и B вызываются из разных потоков, вам нужно быть более осторожными, чтобы делать обработку флагов поточно-безопасным способом (например, с использованием std :: atomic или аналогичного).

Смежные вопросы