В моей реализации потоков используется идиома pimpl, и в классе Impl у меня есть одна версия для каждой ОС, которую я поддерживаю, а также одна, которая использует ускорение, поэтому я могу решить, какую из них использовать при создании проекта.
Я решил создать два класса: один — Thread, который имеет только базовые сервисы, предоставляемые ОС; а другой — SafeThread, который наследуется от Thread и имеет метод для совместного прерывания.
У потока есть метод terminate(), который выполняет навязчивое завершение. Это виртуальный метод, который перегружен в SafeThread, где он сигнализирует об объекте события. Существует (статический) метод yeld(), который время от времени должен вызывать работающий поток; этот метод проверяет, сигнализируется ли объект события, и, если да, генерирует исключение, перехваченное в вызывающей стороне точки входа потока, тем самым завершая поток. Когда это происходит, он сигнализирует о втором объекте события, поэтому вызывающая функция terminate() может знать, что поток был безопасно остановлен.
В случаях, когда существует риск взаимоблокировки, SafeThread::terminate() может принимать параметр тайм-аута. Если тайм-аут истекает, он вызывает Thread::terminate(), тем самым навязчиво убивая поток. Это последний ресурс, когда у вас есть что-то, что вы не можете контролировать (например, сторонний API), или в ситуациях, когда взаимоблокировка наносит больший ущерб, чем утечка ресурсов и тому подобное.
Надеюсь, это будет полезно для вашего решения и даст вам достаточно четкое представление о моем выборе дизайна. Если нет, я могу опубликовать фрагменты кода, чтобы уточнить, если хотите.
person
Fabio Ceconello
schedule
16.05.2010