开发者

boost thread destroys polymorphism

duplicate of: "pure virtual method called" when implementing a boost::thread wrapper interface

I am trying to create a more object oriented version of the threads using boost threads.

So I created a Thread class:

class Thread {
public:
    Thread() {}
    virtual ~Thread() { thisThread->join(); }

    void start() { thisThread = new boost::thread(&Thread::run, this); }

    virtual void run() {};

private:
    boost::thread *thisThread;
};

this class creates the thread in start() l开发者_JS百科ike this:

thisThread = new boost::thread(&Thread::run, this);

The problem is that when I create a class that overwrites the run() method, the run() method from Thread is call by the thread instead of the new run() method

for example I have a class that extends Thread:

class CmdWorker: public Thread {
public:
    CmdWorker() : Thread() {}
    virtual ~CmdWorker() {}

    void run() { /* deosn't get called by the thread */ }
};

when I do

Thread *thread = new CmdWorker();
thread.start(); //---> calls run() from Thread instead of run() from CmdWorker

but just to be more clear:

thread.run();  calls the correct run from CmdWorker, (run() is virtual from Runnable)

Any idea why this happens or how it can be fixed ?

NOTE: I created a function (that has nothing to do with the Thread class)

void callRun(Thread* thread) {
    thread->run();
}

and changed the thread creation to:

thisThread = new boost::thread(callRun, this);

when debugging I noticed that the thread pointer is pointing to a object of type Thread instead of CmdWorker

EDIT:

testcase code at: http://ideone.com/fqMLF and http://ideone.com/Tmva1

Object seems to be sliced (but this is strange since pointers are used)

didn't manage to add boost to it


The answer is in that question:

"pure virtual method called" when implementing a boost::thread wrapper interface

Basically, when the boost::thread object begins running, the object it was run against had the time to be deleted.

You have to implement a join method that you call manually before destroying the object.


when debugging I noticed that the thread pointer is pointing to a object of type Thread instead of CmdWorker

Maybe the CmdWorker object is sliced (i.e. copied by value) into a Thread object somewhere in your code?

Do you get the same behaviour with a minimal test case?


By doing &Thread::Run on a non-virtual function, you are forcing any class that derives from Thread to use the function specified in the Thread base class. Try making Thread::Run a virtual void and see if that fixes your issue.


From reading your updates, you're calling delete in the main thread, while the thread is starting in the other. Depending on the race between the destructor and the invocation of run, it will either:

  1. Crash before it starts, because the vtable is completely destroyed
  2. Call the Thread::run (which is pure virtual, and crashes with a pure virtual thunk)
  3. Call the correct function, which is the derived class run()

If you add a call to sleep(1) after you call start, but before you call delete, you'll find that it works as you expect.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜