CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Pure virtuals and construction order

    I have an AbstractAgent base class that manages a background thread. The actual work done in the background thread is accomplished through a pure virtual function call.

    Here's the problem: because the base class is initialized prior to the derived class, there is a race condition in which the pure virtual call might occur before the derived class is initialized. Likewise, on teardown the derived class might deconstruct before the base class destructor has a chance to stop the thread.

    I'd like to know if there are any well-known patterns for dealing with this problem. All I can think of is providing start() and stop() methods which can be called from the most-derived class's constructor/destructor, but that strikes me as inelegant.

  2. #2
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Pure virtuals and construction order

    you could use a variant of the base from member idiom to enforce construction order ( never used myself, but at least it should qualify as "well known" ).

    That said, I had a similar problem sometime ago ( it was a window rather than a thread ) and I concluded it was the symptom of a design problem. If a class has-a resource that requires subclasses to be alive during ctor in order be valid, it means that those subclasses do not satisfy an is-a relationship. So, either such construction reordering tricks are hidden to the subclasses once for all or it's just asking for troubles.
    In this case, such a base class neither is-a thread nor has-a thread because as, a resource, threads are owned by the OS not by objects ( threads of execution and objects looks like orthogonal concepts to me; note that std/boost thread "are not" threads, they're just light handles; in fact, note that std::thread destructor wisely does neither terminate nor detach the actual thread it refers to and destroying an std::thread who's still joinable is considered an inherently wrong operation ).

  3. #3
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Pure virtuals and construction order

    I don't really like base_from_member much, although I can see how it could occasionally save the day. In this case, though, it's a matter of completely inverting the normal construction/destruction order, not just rearranging a couple of things.

    It's possible I've been spoiled by QT, which tries very hard to let you define an object RUNS-IN thread relationship. When I try to do the same thing myself I run into these problems.

    I could see maybe defining that an object HAS-A thread_control member as one solution, but that isn't a complete solution if you also want the interface to look a certain way. In fact, that's particularly annoying because the two things you need to do (inherit an interface and define a thread_control member) need to be at opposite ends of the class, since thread_control should be constructed last and destructed first.

  4. #4
    Join Date
    Jul 2013
    Posts
    576

    Re: Pure virtuals and construction order

    Quote Originally Posted by Lindley View Post
    All I can think of is providing start() and stop() methods which can be called from the most-derived class's constructor/destructor, but that strikes me as inelegant.
    If anything the design is inelegant because the AbstractAgent base class isn't abstract at all. It starts and stops threads.

  5. #5
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Pure virtuals and construction order

    Quote Originally Posted by Lindley View Post
    Here's the problem: because the base class is initialized prior to the derived class, there is a race condition in which the pure virtual call might occur before the derived class is initialized. Likewise, on teardown the derived class might deconstruct before the base class destructor has a chance to stop the thread.
    This is not a race condition (race conditions are something else entirely).

    If you call the pure virtual, then you have a flat out logic error. (possibly resulting from a design flaw or an incorrect assumption about how things work).

    In the constructor of the derived class, you cannot reliably call virtuals because the vtable may not have been initialized yet.
    If you assume that calling a virtual in a constructor ends up calling the virtual implementation of the derived class. This is an incorrect assumption, it doesn't work that way.


    Not sur eif this applies... but also in case of multithreading, you can't reliably pass a pointer/reference of the class to another thread from the constructor/destructor.



    I'd like to know if there are any well-known patterns for dealing with this problem.
    Impossible to say without actually seeing what you're trying to do.

    But as a whole you need to see a constructor and destructor as "atomic" even if C++ itself doesn't provide anything to ensure that atomicity. AN object doesn't exist until it's finished construction (and the object is in a "hybrid" state along the way), and it stops existing the moment it begins destruction (and destructors are even more nitpicky than constructors).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured