Question

Based on C++ polymorphism with variadic function parameter I tried to write similar (non-templated, with constructors) program

code:

#include <thread>
#include <iostream>
#include <vector>

class Base
{
public:
    Base (int count) { run(count); } // this-> does not help

    virtual void run (int count) { // non-virtual does not help eighter
        for (int i=0; i<count; ++i)
            threads.emplace_back(std::ref(*this));
    }

    virtual ~Base () {
        for (auto& t : threads)
            t.join();
    }

    virtual void operator() () = 0;

protected:
    std::vector< std::thread > threads;
};


class Derived : public Base
{
public:
    using Base::Base;
    virtual void operator() () { std::cout << "d"; }
};


int main()
{
    Derived d(4);
    std::cout << std::endl;
    return 0;
}

expected result:

dddd

real result (Ubuntu 14.04, gcc v4.8.2):

pure virtual method called
pure virtual method called
terminate called without an active exception
terminate called without an active exception
dAborted (core dumped)

Please notice, that Derived::operator() was at least once really called (d on the last line, almost always).

Even though the code is dead simple and almost same as original (see link above) it does not work. I spent literally hours solving this problem.

Target is to construct Derived with a number of threads. This amount of threads will be executed (in constructor) and joined in destructor. operator() should be used as thread-body function (as in the original code). Moreover, it should be virtual in order to provide polymophism.

As far as I'm concerned run passes *this (for some reason) typed as Base, not Derived, so threads execute Base::operator() which is pure virtual

Additional question: is there any way labeling operator() protected?

Can anybody help me out? Thanks.

EDIT:

According to Billy ONeal's answer I rewrote the code, so Derived constructor calls the run, but without any success

#include <thread>
#include <iostream>
#include <vector>

class Base
{
public:
    virtual void run (int count) { // non-virtual does not help eighter
        for (int i=0; i<count; ++i)
            threads.emplace_back(std::ref(*this));
    }

    virtual ~Base () {
        for (auto& t : threads)
            t.join();
    }

    virtual void operator() () = 0;

protected:
    std::vector< std::thread > threads;
};


class Derived : public Base
{
public:
    Derived (int count) { run(count); }
    virtual void operator() () { std::cout << "d"; }
};


int main()
{
    Derived d(4);
    std::cout << std::endl;
    return 0;
}

Results vary over the time - here are all I have ever got

1) d
2) dd
3) ddd
4) dddd
5) d
    pure virtual method called
    terminate called without an active exception
    ddAborted (core dumped)

Especially 5) I can't explain.

I've added {...} around Derived d(4); as an anonymous block to force destructor execution before the endl of line end program termination, but since that I've got only

pure virtual method called
terminate called without an active exception
ddAborted (core dumped)
Was it helpful?

Solution

Your code has a race condition (and therefore undefined behavior). When you start the thread in Base's constructor, the thread will immediately try to call operator() on that object. But Derived's constructor hasn't run yet, so operator() is still the one from Base, which is pure virtual. Another valid execution would be that Base's constructor and Derived's constructor finish before the threads actually get going, which would give the behavior you expect, but that result is unlikely.

Your comment about this->run not helping makes sense because the output complains about a pure virtual member function being called, and run is not a pure virtual member, only operator() is.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top