Здравствуйте!
Я пытаюсь написать некий класс модуля, который по инициализации или по вызову метода run() начинал исполнение в отдельном потоке. При уничтожении объекта поток должен быть воссоединен с материнским. На данный момент я пришел к такой вот реализации (которая собственно не работает, иначе бы я вопросы тут не задавал =) ):class ThreadedModule
{
public:
ThreadedModule() {}
~ThreadedModule()
{
if (_thrd)
{
_thrd->join();
delete _thrd;
}
}void run()
{
this->code();
_thrd = new boost::thread(_run(this));
}
virtual void code()
{
std::cout << "hello from ThreadedModule::code()\n";
}private:
boost::thread *_thrd;
struct _run
{
_run (ThreadedModule *th) : th(th) {}
void operator()()
{
th->code();
}
ThreadedModule *th;
};
};class MyThreadedModule : public ThreadedModule
{
public:
virtual void code() { std::cout << "hello from MyThreadedModule::code()\n"; }
};int main ()
{
MyThreadedModule mod;
mod.run();
}сей код генерирует следующее:
hello from MyThreadedModule::code()
hello from ThreadedModule::code()Первая строка как и следовало ожидать выводится в следствие вызова code() из run(). Как видно полиморфизм работает прекрасно.
Вторая же строка выводится уже в выделенном потоке, в который передается струтура _run() с предеданным в нее поинтером на MyThreadedModule закастованным до ThreadedModule. По идее должен вызываться метод класса MyThreadedModule, а на самом деле вызывется метод базового класса.
Может кто знает как разрешть проблему? Мне самому лично не нравится вся эта чехорда со struct _run() ... operator()(). Может все-таки есть какой-нибудь способ получить пойнтер на виртуальный метод (хотя бы небезопасный)
Попробуй сделать хотябы один метод code не inline
>Попробуй сделать хотябы один метод code не inlineпробовал, никакого эффекта
1. смотри boost::bind :
new boost::thread(boost::bind(&ThreadedModule::run, this);
так мы отказываемся от использования struct _run
2. для полиморфизма мы должны передавать правильный указатель на класс в нашем случае this ??.
3. join в деструкторе - плохое решение.
спасибо за совет по поводу bind, что-то я про него забыл. теперь оно выглядит немного стройнее:class ThreadedModule
{
public:
ThreadedModule() {}
~ThreadedModule()
{
if (_thrd)
{
_thrd->join();
delete _thrd;
}
}void run()
{
std::cout << reinterpret_cast< unsigned int >(this) << '\n';
this->code();
_thrd = new boost::thread(boost::bind(&ThreadedModule::_run, this));
}
virtual void code()
{
std::cout << "hello from ThreadedModule::code()\n";
}private:
boost::thread *_thrd;
static void _run(ThreadedModule *tm)
{
std::cout << reinterpret_cast< unsigned int >(tm) << '\n';
tm->code();
}};
вывод:
3215966904
hello from MyThreadedModule::code()
3215966904
hello from ThreadedModule::code()одна и та же лажа... надо полностью принцип менять. хотя данное поведение сего кода мне кажется полной чушью
Я уже говорил что this - указатель на базовый класс, а тебе нужен указатель на потомка.посмотри что выдаст эта функция:
virtual void code()
{
std::cout << reinterpret_cast< unsigned int >(this) << '\n';
std::cout << "hello from ThreadedModule::code()\n";
}
>Я уже говорил что this - указатель на базовый класс, а тебе
>нужен указатель на потомка.
>
>посмотри что выдаст эта функция:
>
>virtual void code()
>{
> std::cout << reinterpret_cast< unsigned int >(this) << '\n';
> std::cout << "hello from ThreadedModule::code()\n";
>}все тот же пойнтер.