Force method call in destructor of a derived class?

Discussion in 'C++' started by Daniel Kay, Sep 22, 2005.

  1. Daniel Kay

    Daniel Kay Guest

    Hello!

    I have written two template classes which implement the observerpattern
    in C++. I hope I manage to desribe the problem I have.

    template<class T> class Observer {
    /* ... */
    };

    template<class T> classSubject {
    /* ... */
    };

    These template classes are being used as base classes for non abstract
    Observer and Subject classes. The update() method in the observer class
    is pure virtual and needs to be implemented by the class which derives
    the Observer template class. This is good, because the user can't forget
    to implement it.

    In my concept the subject has a list of attached observers, and the
    Observer has a list of subject it was attached to. When a observer is
    destructed for some reason, the destructor detaches itself from all
    Subjects it was attached to.

    Now my problem: At that point, when I am in the destructor of the
    Observer template, the update method isn't available anymore. (Because
    the derived class is already destructed) So in case the Subject now
    tries to notify the observer the application crashes. Of course this
    only happens with a multithreaded application. In normal case this
    condition will happen very very seldom. But it can and will happen some
    day. I have found two ways to resolve this issue. I don't like one of them.

    1. Make the method update() in the observer base class virtual only
    (defining an empty body). The user isn't forced anymore to implement
    update in the derived class of the Observer pattern and might forget it.

    2. By forcing the user to call some method from the destructor of the
    derived class which was defined in the Observer base class which
    detaches itself from all Subjects. The user may forget to insert this
    call in his destructor and we have the problem again.

    Anyone knows a third way to resolve my problem? I hope I managed to
    describe my problem... :D If not, then just ignore it and i am lost... *g*

    Have a nice day,
    Daniel
    Daniel Kay, Sep 22, 2005
    #1
    1. Advertising

  2. * Daniel Kay:
    > [long problem description]


    The short of it seems to be: you need some notification when the client code's
    derived class object is destroyed.

    And one way to do that is to force the client code to use a special template
    class as the most derived class.

    Client code:

    class MyObserverImpl: public Observer { ... };
    typedef ConcreteObserver<MyObserverImpl> MyObserver;

    where ConcreteObserver is a template class you provide, where the destructor
    provides the notification you need.

    You can force use of ConcreteObserver via the virtual base class with private
    constructor and friend trick, described in the FAQ for the case of disallowing
    further inheritance -- making a class "final" or "sealed" -- but I think
    more useful for the case above, forcing a given most derived class.

    One main problem with this technique is how to forward constructor arguments
    from ConcreteObserver to, in the example above, MyObserverImpl. And one
    solution is to require that every constructor except the default constructor
    must have exactly one argument (which can be a struct), and then use a
    templated constructor. There are also other solutions.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Sep 22, 2005
    #2
    1. Advertising

  3. Daniel Kay

    David Hilsee Guest

    "Daniel Kay" <> wrote in message
    news:4332e539$0$62$-online.net...
    > Hello!
    >
    > I have written two template classes which implement the observerpattern
    > in C++. I hope I manage to desribe the problem I have.
    >
    > template<class T> class Observer {
    > /* ... */
    > };
    >
    > template<class T> classSubject {
    > /* ... */
    > };
    >
    > These template classes are being used as base classes for non abstract
    > Observer and Subject classes. The update() method in the observer class
    > is pure virtual and needs to be implemented by the class which derives
    > the Observer template class. This is good, because the user can't forget
    > to implement it.
    >
    > In my concept the subject has a list of attached observers, and the
    > Observer has a list of subject it was attached to. When a observer is
    > destructed for some reason, the destructor detaches itself from all
    > Subjects it was attached to.
    >
    > Now my problem: At that point, when I am in the destructor of the
    > Observer template, the update method isn't available anymore. (Because
    > the derived class is already destructed) So in case the Subject now
    > tries to notify the observer the application crashes. Of course this
    > only happens with a multithreaded application. In normal case this
    > condition will happen very very seldom. But it can and will happen some
    > day. I have found two ways to resolve this issue. I don't like one of

    them.
    >
    > 1. Make the method update() in the observer base class virtual only
    > (defining an empty body). The user isn't forced anymore to implement
    > update in the derived class of the Observer pattern and might forget it.
    >
    > 2. By forcing the user to call some method from the destructor of the
    > derived class which was defined in the Observer base class which
    > detaches itself from all Subjects. The user may forget to insert this
    > call in his destructor and we have the problem again.
    >
    > Anyone knows a third way to resolve my problem? I hope I managed to
    > describe my problem... :D If not, then just ignore it and i am lost... *g*
    >
    > Have a nice day,
    > Daniel


    You shouldn't allow other threads to invoke member functions on an object
    that is destructing unless you have a guarantee from your implementation
    that the "behind the scenes" work that your implementation provides for
    destruction is thread-safe. Your implementation may be messing with the
    vtable or doing other things when you invoke one of the functions. You
    should remove the observer from the subject before object destruction
    begins.

    --
    David Hilsee
    David Hilsee, Sep 22, 2005
    #3
  4. Daniel Kay

    Daniel Kay Guest

    Alf P. Steinbach wrote:
    > * Daniel Kay:
    >
    >>[long problem description]

    >
    >
    > The short of it seems to be: you need some notification when the client code's
    > derived class object is destroyed.
    >
    > And one way to do that is to force the client code to use a special template
    > class as the most derived class.
    >
    > Client code:
    >
    > class MyObserverImpl: public Observer { ... };
    > typedef ConcreteObserver<MyObserverImpl> MyObserver;
    >
    > where ConcreteObserver is a template class you provide, where the destructor
    > provides the notification you need.
    >
    > You can force use of ConcreteObserver via the virtual base class with private
    > constructor and friend trick, described in the FAQ for the case of disallowing
    > further inheritance -- making a class "final" or "sealed" -- but I think
    > more useful for the case above, forcing a given most derived class.
    >
    > One main problem with this technique is how to forward constructor arguments
    > from ConcreteObserver to, in the example above, MyObserverImpl. And one
    > solution is to require that every constructor except the default constructor
    > must have exactly one argument (which can be a struct), and then use a
    > templated constructor. There are also other solutions.


    Thank you for your spare time on giving me some idea on how to solve my
    problem. If no better solutions is being posted I'll try to implement it.

    Thx,
    Daniel
    Daniel Kay, Sep 22, 2005
    #4
  5. Daniel Kay

    Daniel Kay Guest

    David Hilsee wrote:
    > "Daniel Kay" <> wrote in message
    > news:4332e539$0$62$-online.net...
    >
    >>Hello!
    >>
    >>I have written two template classes which implement the observerpattern
    >>in C++. I hope I manage to desribe the problem I have.
    >>
    >>template<class T> class Observer {
    >>/* ... */
    >>};
    >>
    >>template<class T> classSubject {
    >>/* ... */
    >>};
    >>
    >>These template classes are being used as base classes for non abstract
    >>Observer and Subject classes. The update() method in the observer class
    >>is pure virtual and needs to be implemented by the class which derives
    >>the Observer template class. This is good, because the user can't forget
    >>to implement it.
    >>
    >>In my concept the subject has a list of attached observers, and the
    >>Observer has a list of subject it was attached to. When a observer is
    >>destructed for some reason, the destructor detaches itself from all
    >>Subjects it was attached to.
    >>
    >>Now my problem: At that point, when I am in the destructor of the
    >>Observer template, the update method isn't available anymore. (Because
    >>the derived class is already destructed) So in case the Subject now
    >>tries to notify the observer the application crashes. Of course this
    >>only happens with a multithreaded application. In normal case this
    >>condition will happen very very seldom. But it can and will happen some
    >>day. I have found two ways to resolve this issue. I don't like one of

    >
    > them.
    >
    >>1. Make the method update() in the observer base class virtual only
    >>(defining an empty body). The user isn't forced anymore to implement
    >>update in the derived class of the Observer pattern and might forget it.
    >>
    >>2. By forcing the user to call some method from the destructor of the
    >>derived class which was defined in the Observer base class which
    >>detaches itself from all Subjects. The user may forget to insert this
    >>call in his destructor and we have the problem again.
    >>
    >>Anyone knows a third way to resolve my problem? I hope I managed to
    >>describe my problem... :D If not, then just ignore it and i am lost... *g*
    >>
    >>Have a nice day,
    >>Daniel

    >
    >
    > You shouldn't allow other threads to invoke member functions on an object
    > that is destructing unless you have a guarantee from your implementation
    > that the "behind the scenes" work that your implementation provides for
    > destruction is thread-safe. Your implementation may be messing with the
    > vtable or doing other things when you invoke one of the functions. You
    > should remove the observer from the subject before object destruction
    > begins


    Hello David!

    Right now the destructor of the observer base class does the following
    to protect itself from calling subjects.

    Make sure that all subjects the observer is attached to won't try to
    call the update() method by invoking the lock() method of all subject
    instances. Then I detach from all subjects. Then I invoke unlock() for
    all subjects, so they can continue their work.

    The time between destructing the derived instance and locking all
    subjects is critical. Of course one solution is to call a method defined
    in the observer base class before I destruct the derived class. But
    there must be a better way in resolving this problem.

    Bye,
    Daniel Kay
    Daniel Kay, Sep 22, 2005
    #5
  6. Daniel Kay

    David Hilsee Guest

    "Daniel Kay" <> wrote in message
    news:4332f17a$0$16488$-online.net...
    [...]
    >
    > Hello David!
    >
    > Right now the destructor of the observer base class does the following
    > to protect itself from calling subjects.
    >
    > Make sure that all subjects the observer is attached to won't try to
    > call the update() method by invoking the lock() method of all subject
    > instances. Then I detach from all subjects. Then I invoke unlock() for
    > all subjects, so they can continue their work.
    >
    > The time between destructing the derived instance and locking all
    > subjects is critical. Of course one solution is to call a method defined
    > in the observer base class before I destruct the derived class. But
    > there must be a better way in resolving this problem.


    OK, I just wanted to make sure that you understood that "solution" #1
    suffers from multithreading issues.

    I suppose you could always write a little handle class that holds on to the
    observer and does the work for you. In its destructor, you could detach the
    observer from the subjects before you destruct the object. Then you always
    hold on to observers using that wrapper class instead of just using the
    Observer class.

    class ObserverHandle {
    Observer * observer;

    //...
    ~ObserverHandle() {
    observer->DetachFromSubjects();
    delete observer;
    }
    };

    --
    David Hilsee
    David Hilsee, Sep 23, 2005
    #6
  7. Daniel Kay

    Greg Guest

    Daniel Kay wrote:
    > Hello!
    >
    > I have written two template classes which implement the observerpattern
    > in C++. I hope I manage to desribe the problem I have.
    >
    > template<class T> class Observer {
    > /* ... */
    > };
    >
    > template<class T> classSubject {
    > /* ... */
    > };
    >
    > These template classes are being used as base classes for non abstract
    > Observer and Subject classes. The update() method in the observer class
    > is pure virtual and needs to be implemented by the class which derives
    > the Observer template class. This is good, because the user can't forget
    > to implement it.
    >
    > In my concept the subject has a list of attached observers, and the
    > Observer has a list of subject it was attached to. When a observer is
    > destructed for some reason, the destructor detaches itself from all
    > Subjects it was attached to.
    >
    > Now my problem: At that point, when I am in the destructor of the
    > Observer template, the update method isn't available anymore. (Because
    > the derived class is already destructed) So in case the Subject now
    > tries to notify the observer the application crashes. Of course this
    > only happens with a multithreaded application. In normal case this
    > condition will happen very very seldom. But it can and will happen some
    > day. I have found two ways to resolve this issue. I don't like one of them.
    >
    > 1. Make the method update() in the observer base class virtual only
    > (defining an empty body). The user isn't forced anymore to implement
    > update in the derived class of the Observer pattern and might forget it.
    >
    > 2. By forcing the user to call some method from the destructor of the
    > derived class which was defined in the Observer base class which
    > detaches itself from all Subjects. The user may forget to insert this
    > call in his destructor and we have the problem again.
    >
    > Anyone knows a third way to resolve my problem? I hope I managed to
    > describe my problem... :D If not, then just ignore it and i am lost... *g*
    >
    > Have a nice day,
    > Daniel


    Why not implement Observer::Update() but keep it a pure virtual
    function so subclasses still have to implement it themselves?

    Greg
    Greg, Sep 23, 2005
    #7
  8. Daniel Kay

    Daniel Kay Guest

    Greg wrote:
    > Daniel Kay wrote:
    >
    >>Hello!
    >>
    >>I have written two template classes which implement the observerpattern
    >>in C++. I hope I manage to desribe the problem I have.
    >>
    >>template<class T> class Observer {
    >>/* ... */
    >>};
    >>
    >>template<class T> classSubject {
    >>/* ... */
    >>};
    >>
    >>These template classes are being used as base classes for non abstract
    >>Observer and Subject classes. The update() method in the observer class
    >>is pure virtual and needs to be implemented by the class which derives
    >>the Observer template class. This is good, because the user can't forget
    >>to implement it.
    >>
    >>In my concept the subject has a list of attached observers, and the
    >>Observer has a list of subject it was attached to. When a observer is
    >>destructed for some reason, the destructor detaches itself from all
    >>Subjects it was attached to.
    >>
    >>Now my problem: At that point, when I am in the destructor of the
    >>Observer template, the update method isn't available anymore. (Because
    >>the derived class is already destructed) So in case the Subject now
    >>tries to notify the observer the application crashes. Of course this
    >>only happens with a multithreaded application. In normal case this
    >>condition will happen very very seldom. But it can and will happen some
    >>day. I have found two ways to resolve this issue. I don't like one of them.
    >>
    >>1. Make the method update() in the observer base class virtual only
    >>(defining an empty body). The user isn't forced anymore to implement
    >>update in the derived class of the Observer pattern and might forget it.
    >>
    >>2. By forcing the user to call some method from the destructor of the
    >>derived class which was defined in the Observer base class which
    >>detaches itself from all Subjects. The user may forget to insert this
    >>call in his destructor and we have the problem again.
    >>
    >>Anyone knows a third way to resolve my problem? I hope I managed to
    >>describe my problem... :D If not, then just ignore it and i am lost... *g*
    >>
    >>Have a nice day,
    >>Daniel

    >
    >
    > Why not implement Observer::Update() but keep it a pure virtual
    > function so subclasses still have to implement it themselves?


    I don't understand...

    class PureVirtualMethod {
    virtual void update(Subject* s) = 0;
    };

    class VirtualMethod {
    virtual void update(Subject* s) { };
    };

    I am not forced to define an own version of update(Subject* s) with the
    second class. Or is there any way to define it in the base class but
    also force the user to define his own? Would be new to me.

    Today I had a look at the boost libraries. And I had a look at
    signal/slot template which seems simular to the technique used by QT.
    Maybe that's the solution for my problem. Thanks to everyone...

    Cya,
    Daniel Kay
    Daniel Kay, Sep 23, 2005
    #8
  9. Daniel Kay

    red floyd Guest

    Daniel Kay wrote:

    >
    > class PureVirtualMethod {
    > virtual void update(Subject* s) = 0;
    > };
    >


    As I understand it, the following is legal;

    class PureVirtualMethod {
    public:
    virtual void update(Subject* s) = 0;
    };

    void PureVirtualMethod::update(Subject* s)
    {
    // some implementation
    }

    class NonPure : public PureVirtualMethod
    {
    public:
    void update(Subject* s)
    {
    // my implementation specific details here
    // followed by common code
    PureVirtualMethod::update(s);
    }
    };
    red floyd, Sep 23, 2005
    #9
  10. Daniel Kay

    Greg Guest

    Daniel Kay wrote:
    > Greg wrote:
    > > Daniel Kay wrote:
    > >
    > >>Hello!
    > >>
    > >>I have written two template classes which implement the observerpattern
    > >>in C++. I hope I manage to desribe the problem I have.
    > >>
    > >>template<class T> class Observer {
    > >>/* ... */
    > >>};
    > >>
    > >>template<class T> classSubject {
    > >>/* ... */
    > >>};
    > >>
    > >>These template classes are being used as base classes for non abstract
    > >>Observer and Subject classes. The update() method in the observer class
    > >>is pure virtual and needs to be implemented by the class which derives
    > >>the Observer template class. This is good, because the user can't forget
    > >>to implement it.
    > >>
    > >>In my concept the subject has a list of attached observers, and the
    > >>Observer has a list of subject it was attached to. When a observer is
    > >>destructed for some reason, the destructor detaches itself from all
    > >>Subjects it was attached to.
    > >>
    > >>Now my problem: At that point, when I am in the destructor of the
    > >>Observer template, the update method isn't available anymore. (Because
    > >>the derived class is already destructed) So in case the Subject now
    > >>tries to notify the observer the application crashes. Of course this
    > >>only happens with a multithreaded application. In normal case this
    > >>condition will happen very very seldom. But it can and will happen some
    > >>day. I have found two ways to resolve this issue. I don't like one of them.
    > >>
    > >>1. Make the method update() in the observer base class virtual only
    > >>(defining an empty body). The user isn't forced anymore to implement
    > >>update in the derived class of the Observer pattern and might forget it.
    > >>
    > >>2. By forcing the user to call some method from the destructor of the
    > >>derived class which was defined in the Observer base class which
    > >>detaches itself from all Subjects. The user may forget to insert this
    > >>call in his destructor and we have the problem again.
    > >>
    > >>Anyone knows a third way to resolve my problem? I hope I managed to
    > >>describe my problem... :D If not, then just ignore it and i am lost... *g*
    > >>
    > >>Have a nice day,
    > >>Daniel

    > >
    > >
    > > Why not implement Observer::Update() but keep it a pure virtual
    > > function so subclasses still have to implement it themselves?

    >
    > I don't understand...
    >
    > class PureVirtualMethod {
    > virtual void update(Subject* s) = 0;
    > };
    >
    > class VirtualMethod {
    > virtual void update(Subject* s) { };
    > };
    >
    > I am not forced to define an own version of update(Subject* s) with the
    > second class. Or is there any way to define it in the base class but
    > also force the user to define his own? Would be new to me.


    I bet that you would not be the only C++ programmer to be surprised by
    the fact that pure virtual functions can be defined. In fact, sometimes
    a pure virtual function must be defined, according to the Standard:

    A pure virtual function need be defined only if
    explicity called with the qualified-id syntax. [10.4.2]

    In other words, if Observer::update() is called explicitly from
    anywhere than that pure virtual function must be defined. Otherwise
    defining it is optional. Since the program is crashing because
    Observer::update is not defined, defining Observer::update() should fix
    the crash with only three lines of empty code:

    void Observer::update()
    {
    // do nothing
    }

    Note that the pure virtual syntax prevents the definition and the
    declaration from being combined. So the definition of a pure virtual
    function must always appear on its own.

    In fact a pure virtual function can override a non-pure function in a
    base class. So Observer could inherit from a base class with a nonpure
    update() that it would override with a pure update(). But it is simpler
    just for Observer to implement update() itself as a pure virtual
    function, than to implement a more complicated solution.

    Greg
    Greg, Sep 24, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. frs
    Replies:
    20
    Views:
    737
    Alf P. Steinbach
    Sep 21, 2005
  2. arun
    Replies:
    2
    Views:
    534
    benben
    Jun 13, 2006
  3. Hubert Fritz
    Replies:
    6
    Views:
    792
    Greg Herlihy
    Jan 28, 2007
  4. Replies:
    1
    Views:
    387
    myork
    May 23, 2007
  5. Replies:
    1
    Views:
    375
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page