Стоит ли закрывать элемент потока класса в деструкторе класса?

Каков наилучший способ закрыть поток 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
    }
}

Это хорошая идея, чтобы закрыть поток в деструкторе класса, как это, или я должен предоставить общедоступный метод, который позволяет пользователю сделать это до того, как объект будет уничтожен, когда есть больше возможностей для обработки ошибок и/или принудительное уничтожение потока, если процедура потока не может завершиться корректно или своевременно?

Уборка беспорядка моего объекта в его деструкторе привлекательна, так как потребует от пользователя меньше внимания к деталям (абстракция, ура!), но мне кажется, что я должен делать что-то в деструкторе только в том случае, если я могу гарантировать получение полная ответственность за успешную и тщательную очистку, и есть небольшой шанс, что коду вне класса однажды может понадобиться знать, был ли поток закрыт корректно.

Кроме того, является ли механизм, который я использую — запись в переменную-член объекта в стеке одного потока и чтение этой переменной в другом потоке — безопасным и разумным?

18
задан bythescruff 27 June 2012 в 12:49
поделиться