2016-08-31 2 views
0

Я использую импульс, чтобы начать нить и функцию нити является функцией член моего класса так же, как это:Как проверить деструктор был вызван в потоке?

class MyClass { 
public: 
    void ThreadFunc(); 
    void StartThread() { 
     worker_thread_ = boost::shared_ptr<boost::thread>(
     new boost::thread(boost::bind(&MyClass::ThreadFunc, this))); 
    } 
}; 

я получить доступ к некоторым переменным-членам в ThreadFunc:

while (!stop) {  
    Sleep(1000); // here will be some block operations 
    auto it = this->list.begin(); 
    if (it != this->list.end()) 
     ... 
} 

I не может ждать вечно для возвращения потока, поэтому я таймаут:

stop = true; 
worker_thread_->interrupt(); 
worker_thread_->timed_join(boost::posix_time::milliseconds(timeout_ms)); 

После тайм-аута, я буду удалять этот MyClass пуанты р. Здесь будет проблема, ThreadFunc не вернется, у нее будут шансы получить доступ к и ее переменным-членам. В моем случае, итератор будет недействительным, и it != this->list.end() будет правдой, поэтому моя программа потерпит крах при использовании недействительного итератора.

Мой вопрос: как его избежать? Или как проверить, действителен ли this или переменные-члены? Или я могу установить некоторые флаги, чтобы сообщить ThreadFunc, что деструктор был вызван?

+0

Зачем вам удаляться 'MyClass', если он все еще используется? Кажется, плохая конструкция. Если вам нужен поток, который по-прежнему будет полуприменим без 'MyClass', тогда он не должен быть членом.Вам понадобится синхронизация вокруг того, что может быть украдено из-под вас. Вероятно, лучше всего использовать атомный общий указатель MyClass. И иметь 'ThreadFunc' - свободную функцию, которая принимает ее как параметр. – vu1p3n0x

+0

@ vu1p3n0x Да, я думаю, что это плохой дизайн, общий указатель кажется хорошим. – zzy

+0

Возможно, вам необходимо синхронизировать доступ к данным, совместно используемым между потоками. –

ответ

2

Существует множество возможных решений. Один из них - использовать класс shared_ptr и позволить потоку удерживать свой класс shared_ptr. Таким образом, объект будет автоматически уничтожен только тогда, когда оба потока будут выполнены с ним.

+0

Спасибо, shared_ptr будет достаточно, чтобы решить мою проблему. Кстати, как насчет решения без повышения? – zzy

+0

@zzy «как о решении без boost» C++ 11 имеет как 'shared_ptr', так и' thread' в std (соответственно заголовки памяти и заголовков). –

+0

@AdrianColomitchi Извините, меня интересуют решения без 'shard_ptr'. – zzy

0

Как насчет того, чтобы создать флаг stopProcessing (сделать его атомарным) в качестве члена MyClass и в вашем методе ThreadFunc проверить каждый цикл, если этот флаг установлен?

[EDIT: сделать четче ответ] Там через два ортогональных проблемы:

  1. останавливая обработку (я потерял терпение, останавливайся, пожалуйста). Это можно установить, установив флаг в MyClass и сделать ThreadFunc, проверяя его как можно чаще.

  2. освобождение ресурсов. Это лучше всего использовать с помощью RAII - одним из примеров является использование shared_ptr

Лучше сохранить их как отдельные проблемы.

Объединение их в одну операцию может быть возможно, но рискованно.
E.g. если вы используете shared_ptr, то когда соединительный поток решил «у меня было достаточно», он просто выходит из блока, который сохраняет свою «копию» shared_ptr, поэтому shared_ptr::use_count получает декремент. Функция потока может заметить это и решить интерпретировать его как «у вызывающего», и прервать обработку.
Однако это означает, что в будущих выпусках никто (но два потока) не может получить shared_ptr, в противном случае «контракт» «декрементированного use_count означает прерывание» нарушен.

(a use_count==1 состояние все еще может быть использовано - интерпретация «Только я, обрабатывающая нить, кажется, интересуется результатами, нет потребителя для них, лучше прекратите работу»).

+0

Будет ли «stopProcessing» уничтожен деструктором? – zzy

+0

@zzy - я предлагаю отделить прерывание обработки от разрушения. Почему вы хотите использовать «уничтожение объекта» в качестве сигнала «прекратить обработку, я слишком долго ждал»? –

+0

Вы правы, нить должна избегать этого. – zzy

Смежные вопросы