Проблема с потоками (погоня за собственным хвостом) - PullRequest
1 голос
/ 08 декабря 2008

Есть ConnectionManager, который ожидает входящих соединений. Для каждого входящего соединения создается экземпляр Connection, который обрабатывает входящий и исходящий трафик этого соединения. Каждый Connection имеет Watchdog, который обрабатывает условия «плохое соединение» и звонки зарегистрированных «Listerners». Один «прослушиватель» - это ConnectionManager, который закрывает соединение и удаляет экземпляр Connection, который, в свою очередь, удаляет соответствующий сторожевой таймер.

Wait. А. Минута.

Watchdog вызывает ConnectionManager, который удаляет Connection, который удаляет Watchdog? Сторожевой пес преследует свой собственный хвост.

Я полностью заблокирован. Как мне решить эту проблему?


Решение : Я сделаю слушателя асинхронным, хотя я пока не знаю, как это сделать без особой боли. Watchdog не знает о ConnectionManager. Это довольно общий характер. Кроме того, в Win32-Thread-API нет ничего похожего на «join», поэтому мне может понадобиться свернуть свои собственные с GetExitCodeThread() и STILL_ACTIVE ...

Спасибо, ребята.

Ответы [ 4 ]

3 голосов
/ 08 декабря 2008

сообщения.

Вместо того, чтобы Watchdog вызывал метод ConnectionManager, отправьте сообщение в очередь в диспетчере соединений. Эта очередь должна быть поточно-ориентированной. Когда ConnectionManager обрабатывает очередь в своем потоке, будет безопасно ожидать окончания потока подключения.

Watchdog          Queue               ConnectionManager
   |                |                        |
Kill Connection---->|                        |
   |                |<-------------------Get Message
  ---               |                        |
                    |-------------------->Process Message
                    |                        |
                    |                     Kill Connection
2 голосов
/ 08 декабря 2008

Если сторожевой таймер работает в другом потоке, проблема не так уж и велика - сторожевой таймер сообщает, что ConnectionManager удаляет асинхронное сообщение, а затем выходит из собственного потока.

Тем временем поток ConnectionManager получает сообщение об удалении и начинает удалять сторожевой таймер.

Чтобы избежать состояния гонки, деструктор сторожевого таймера должен присоединиться к сторожевому потоку и очистить его. (Возможно, также сигнализирует потоку сторожевого устройства или assert () что-то о том, что поток сторожевого устройства готов к выходу).

2 голосов
/ 08 декабря 2008

Если каждый из этих объектов работает в своем собственном потоке, проблем нет.

Watchdog уведомляет ConnectionManager и возвращает.
На этом этапе поток Watchdog может просто выйти.

Когда ConnectionManager замечает событие сторожевого таймера, он уничтожает поток соединения.

0 голосов
/ 08 декабря 2008

Если вы осторожны, проблем нет.

  1. ConnectionInstance :: a_method () вызывает Watchdog :: a_method () вызывает ConnectionManager :: a_method

  2. ConnectionManager :: a_method () удаляет ConnectionInstance удаляет Watchdog

  3. ConnectionManager :: a_method () возвращается к Watchdog :: a_method () возвращается к ConnectionInstance :: a_method (). Пока обратный путь не имеет доступа ни к каким членам, это просто возврат из функции. Код все еще там по стандарту, так что вы можете безопасно вернуться.

Это требует тщательного кодирования и сопровождения, но это не грязный взлом, как может показаться.

Асинхронный протокол потребует такого же количества размышлений. Вам не нужно избегать гонок между Watchdog, запрашивающим удаление в ConnectionManager :: queue и ConnectionManager, одновременно выполняющим какие-то действия с очередью. Проблема глубже: есть период времени, когда ConnectionInstance не работает - он запросил удаление - но все равно не удаляется. Что это делает? Код не может оставаться на месте. Если есть надежный выход для несуществующего ConnectionInstance, вы также можете самостоятельно откатить стек без создания дополнительных асинхронных протоколов.

Сторожевая функция, генерирующая исключение, может быть более простым способом работы с ConnectionInstance, если они находятся в одном потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...