Присоединение к экземпляру boost :: thread в деструкторе - PullRequest
9 голосов
/ 02 ноября 2009

Я вижу проблему, из-за которой обращение к потоку boost-> join в деструкторе приводит к тупику. Я не понимаю, почему, и я не слишком заинтересован в том, чтобы сохранить код, который просто работает (и я не понимаю, почему) в проекте.

Объявление класса (для краткости я удалил метод run () из try / catch: согласно документации потока поддержки результат должен быть одинаковым с или без него):

class B 
{
public:
    void operator()(){run();}
    void run();
    void shutdown();
    ~B();
    B();
    boost::thread *thr;
    bool shutdown_requested;
};

void B::shutdown()
{
    shutdown_requested = true;

    if (thr != NULL)
    {
        thr->interrupt();
        thr->join(); // deadlock occurs here!
        delete thr;
        thr = NULL;
    }
}

B::~B()
{
    shutdown();
}

B::B()
{
    thr = new boost::thread(boost::ref(*this));
}

void B::run()
{
    while (!shutdown_requested)
    {
        boost::xtime xt;
        boost::xtime_get(&xt, boost::TIME_UTC);
        xt.sec += 30;
        boost::this_thread::sleep(xt);
    }
}

Фрагмент, который не работает:

int main()
{
    B *b = new B;

    Sleep(5000);
    printf("deleting \n");fflush(stdout);
//    b->shutdown();
    delete b;
    printf("done\n");fflush(stdout);

    return 0;
}

Фрагмент, который работает:

int main()
{
    B *b = new B;

    Sleep(5000);
    printf("deleting \n");fflush(stdout);
    b->shutdown();
    delete b;
    printf("done\n");fflush(stdout);

    return 0;
}

Я думаю, что причина этого поведения как-то связана с этим фрагментом документации повышения:

пользователь Boost.Thread должен обеспечить что упомянутый объект переживает вновь созданный поток исполнения.

Но я не совсем понимаю, почему тупик - присоединение к потоку не вызовет деструктор в B, а сам объект не будет удален, когда предполагается, что метод run () завершится.

1 Ответ

4 голосов
/ 02 ноября 2009

Я нашел проблему: она сводится к чрезмерно усердному программисту.

Первоначально я скомпилировал свой проект, используя DUMA (http://sourceforge.net/projects/duma/), чтобы проверить, не была ли моя реализация текущего модуля без утечек. К сожалению, в моей тестовой песочнице также были включены настройки duma, которых я не понимал до Я прошел по коду в отладчике.

После удаления всех обнаружений утечки памяти все работает как положено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...