Я вижу проблему, из-за которой обращение к потоку 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 () завершится.