Каков наилучший способ закрыть поток Boost, управляемый классом C++, когда пришло время уничтожить объект этого класса? У меня есть класс, который создает и запускает поток при построении и предоставляет общедоступный метод Wake()
, который пробуждает поток, когда пришло время выполнить какую-либо работу.Метод Wake()
использует мьютекс Boost и переменную условия Boost для подачи сигнала потоку; процедура потока ожидает переменную условия, затем выполняет работу и возвращается к ожиданию.
На данный момент я закрыл этот поток в деструкторе класса, используя логическую переменную-член в качестве «работающего» флага; Я сбрасываю флаг, а затем вызываю notify_one() для условной переменной. Затем процедура потока просыпается, замечает, что "running" имеет значение false, и возвращается. Вот код:
class Worker
{
public:
Worker();
~Worker();
void Wake();
private:
Worker(Worker const& rhs); // prevent copying
Worker& operator=(Worker const& rhs); // prevent assignment
void ThreadProc();
bool m_Running;
boost::mutex m_Mutex;
boost::condition_variable m_Condition;
boost::scoped_ptr<boost::thread> m_pThread;
};
Worker::Worker()
: m_Running(true)
, m_Mutex()
, m_Condition()
, m_pThread()
{
m_pThread.reset(new boost::thread(boost::bind(&Worker::ThreadProc, this)));
}
Worker::~Worker()
{
m_Running = false;
m_Condition.notify_one();
m_pThread->join();
}
void Worker::Wake()
{
boost::lock_guard<boost::mutex> lock(m_Mutex);
m_Condition.notify_one();
}
void Worker::ThreadProc()
{
for (;;)
{
boost::unique_lock<boost::mutex> lock(m_Mutex);
m_Condition.wait(lock);
if (! m_Running) break;
// do some work here
}
}
Это хорошая идея, чтобы закрыть поток в деструкторе класса, как это, или я должен предоставить общедоступный метод, который позволяет пользователю сделать это до того, как объект будет уничтожен, когда есть больше возможностей для обработки ошибок и/или принудительное уничтожение потока, если процедура потока не может завершиться корректно или своевременно?
Уборка беспорядка моего объекта в его деструкторе привлекательна, так как потребует от пользователя меньше внимания к деталям (абстракция, ура!), но мне кажется, что я должен делать что-то в деструкторе только в том случае, если я могу гарантировать получение полная ответственность за успешную и тщательную очистку, и есть небольшой шанс, что коду вне класса однажды может понадобиться знать, был ли поток закрыт корректно.
Кроме того, является ли механизм, который я использую — запись в переменную-член объекта в стеке одного потока и чтение этой переменной в другом потоке — безопасным и разумным?