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