Поскольку я начал создавать небольшой проект, целью которого является поддержка кроссплатформенности, я выбрал boost 1.47 для взаимодействия с базовой ОС. Мой проект нуждался в многопоточности, поэтому я выполнил небольшую обертку над буст-потоками, чтобы удовлетворить свои потребности.
Мало я знал, что boost, очевидно, оставляет поток в памяти после разрушения его объекта (?), Или же он может иметь какую-то возможность утечки памяти.
Реализация моей обертки имеет scoped_ptr типа thread, и ptr с областью видимости инициализируется, когда кто-либо вызывает функцию start () в классе обертки. Работающий поток будет остановлен из основного потока с помощью thread-> interrupt (), а деструктор будет вызван из функции-оболочки. (Деструктор структуры процедуры потока, в которой есть оператор () ().
Вот реализация класса оболочки:
(примечание: i_exception и пара других функций являются частью других компонентов проекта)
#define TIMED_JOIN boost::posix_time::milliseconds(1)
namespace utils
{
struct thread_threadable
{
template<typename T> friend class ut_thread;
private:
boost::shared_ptr<thread_threadable> instance;
public:
virtual ~thread_threadable() {}
virtual void operator()() = 0;
};
template<typename T = thread_threadable>
class ut_thread
{
public:
typedef T proc_t;
private:
boost::scoped_ptr<boost::thread> thr;
boost::shared_ptr<proc_t> proc;
public:
explicit ut_thread(const boost::shared_ptr<proc_t> &procedure) : proc(procedure) {}
~ut_thread();
void start();
void stop();
bool running() const {return this->thr.get() != NULL;}
proc_t &procedure() const
{
BOOST_ASSERT(this->proc.get() != NULL);
return *this->proc;
}
};
}
typedef utils::thread_threadable threadable;
template<typename T>
utils::ut_thread<T>::~ut_thread()
{
if(this->thr.get() != NULL)
{
BOOST_ASSERT(this->proc.get() != NULL);
this->stop();
}
}
template<typename T>
void utils::ut_thread<T>::start()
{
if(this->thr.get() != NULL)
i_exception::throw_this("another thread of this procedure is already running");
if(this->proc.get() == NULL)
i_exception::throw_this("procedure object not initialized");
this->proc->instance = this->proc;
this->thr.reset(new boost::thread(boost::ref(*this->proc)));
this->thr->timed_join(TIMED_JOIN);
}
template<typename T>
void utils::ut_thread<T>::stop()
{
if(this->thr.get() == NULL)
i_exception::throw_this("no thread was running");
this->thr->interrupt();
this->proc->~T();
this->thr.reset(NULL);
}
И затем, проверив функциональность этого класса-оболочки, я сделал тест для main.cpp:
struct my_thr : public utils::thread_threadable
{
void operator()()
{
while(true);
}
};
int main()
{
while(true)
{
utils::ut_thread<> thr(boost::shared_ptr<threadable>(new my_thr));
utils::ut_thread<> thr1(boost::shared_ptr<threadable>(new my_thr));
thr.start();
thr1.start();
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
return 0;
}
В этот момент я заметил, что эти потоки не разрушаются, они будут оставаться в памяти, пока программа не завершится. Они также продолжают выполнять оператор while (true).
Итак, я спрашиваю, что может быть причиной такого поведения? Это что-то определено, или просто ошибка или что-то еще?