Generalized "observer" pattern

Discussion in 'C++' started by Gianni Mariani, Sep 23, 2007.

  1. Two issues here:

    a) What is the accepted definition of "observer pattern". While I can't
    point to anything specific, I do remember having issues with
    inconsistency in the definition.

    b) Generic observer design in C++. I have been pushing the Austria
    "Twin" interface for a while and more recently the multi threaded
    version of it "TwinMT" (see the 6129 alpha on sourceforge)

    I am trying to distill the "fundamental" hard problems in software
    development, especially regarding C++ and I've seen too many issues
    relating to the observer pattern I think it is elevated to "fundamental".

    By fundamental issues I mean, "avoiding deadlock conditions", object
    lifetime management etc.

    There is no specific question really, just an invitiation for thoughts
    on the topic.
     
    Gianni Mariani, Sep 23, 2007
    #1
    1. Advertising

  2. Gianni Mariani

    werasm Guest

    Gianni Mariani wrote:
    > Two issues here:
    >
    > a) What is the accepted definition of "observer pattern". While I can't
    > point to anything specific, I do remember having issues with
    > inconsistency in the definition.


    I'm not sure I know what you mean by accepted definition. Interface
    Specification?

    e.g:

    Subject:
    Register: Observer.
    Unregister: Observer.
    Update: State

    Observer:
    Notify: State

    Wikipedia has an interface specification. Whether this is accepted is
    another
    question, but it is based on the original GOF pattern.

    There are also a couple of variations.

    Push/Pull: Do you push the data during notification, or do each of the
    observers
    have an interface to the subject, pulling data after notification.

    Aspect: Observers could register for interests in specific aspects. I
    don't like this,
    though, as I prefer an observer interface per aspect e.g. If you have
    a new aspect,
    you have a new "Twin" as you would call it.

    > b) Generic observer design in C++. I have been pushing the Austria
    > "Twin" interface for a while and more recently the multi threaded
    > version of it "TwinMT" (see the 6129 alpha on sourceforge)


    I have briefly seen it in the past, yes. Will have to look again as it
    was
    not recent.

    > I am trying to distill the "fundamental" hard problems in software
    > development, especially regarding C++ and I've seen too many issues
    > relating to the observer pattern I think it is elevated to "fundamental".


    One of the things we have done in our subject/observer pairs, is to
    have
    no coupling between the subject and observer, but the subject just
    dispatches the data that is of interest. Notify then becomes
    notify( data ) instead of notify( observer ). This is especially
    beneficial (IMO) in a MT environment to prevent coupling of
    observers in other threads.

    Obviously unsubscription especially does cause thread coupling,
    but I've found that that only takes place during deletion, often only
    at the end of the program when only on tread of execution exists.
    I'm very conservative wrt. this. IMO it's better to ensure that your
    application framework starts/stops in a controlled way than to cater
    for the worse case. The caveats obviously need to be documented.

    Another issue is whether to us RAII as subscription/unsubscription
    mechanism. This can reduce lots of coding, but in certain cases
    can be dangerous (and actually, if you want to be exception safe,
    its probably necessary). The dangerous cases are when you have
    circular observers, so to speak. A subject observers another subject
    and visa versa. Keeping a weak pointer to the Subject that the
    observer is associated with solves this easy, though. Usually my
    observer lists are normal pointers, whilst for the association:

    Observer -> Subject

    I use a weak pointer so that the observer does not detach from
    a non-existent subject. I find that the circular dependency in this
    case can be quite common. Also, subscription/unsubscription
    take place much less often than notification, therefore having
    a weak pointer for this relationship makes sense.

    Regards,

    Werner
     
    werasm, Sep 24, 2007
    #2
    1. Advertising

  3. Gianni Mariani

    werasm Guest

    Gianni Mariani wrote:

    > a) What is the accepted definition of "observer pattern". While I can't
    > point to anything specific, I do remember having issues with
    > inconsistency in the definition.


    Aside, and probably OT, I've written a little generic class that
    performs
    RAII subscription/unsubsription. I attempted to make it definition
    independent, handling either attach/detach, subscribe/unsubscribe or
    add/remove as potential interface. It was merely a nice exercise for
    SFINAE (and credit to some posts in c.l.c++, as well as boost
    archives).

    CAVEAT: Does not use weak pointer yet as described in my other
    mail. I just at the time of writing this have not thought of that
    problem
    yet.

    Here goes:

    namespace AviGen {
    namespace GenSubPriv{

    typedef char (&subscribe)[0];
    typedef char (&add)[1];
    typedef char (&attach)[2];
    template < typename T, void (T::*)() >
    struct ptmf_helper {};

    template< typename T > subscribe get_method_literal( ... ); //
    Subscribe
    template< typename T > add
    get_method_literal( ptmf_helper<T,&T::add>* );
    template< typename T > attach
    get_method_literal( ptmf_helper<T,&T::attach>* );

    template <class PubT, class SubT, std::size_t>
    class GenSubBase;

    // Used subscribe/unsubscribe to subscribe.
    template <class PubT, class SubT>
    class GenSubBase<PubT, SubT, sizeof(subscribe)> : public SubT
    {
    protected:
    GenSubBase( PubT& publisher ): publisher_( publisher )
    { publisher_.subscribe( *this ); }
    virtual ~GenSubBase()
    { publisher_.unsubscribe( *this ); }
    private:
    PubT* publisher_;
    };

    // Used add/remove to subscribe.
    template <class PubT, class SubT>
    class GenSubBase<PubT, SubT, sizeof(add)> : public SubT
    {
    protected:
    GenSubBase( PubT& publisher ): publisher_( publisher )
    { publisher_.add( *this ); }
    virtual ~GenSubBase()
    { publisher_.remove( *this ); }
    private:
    PubT* publisher_;
    };

    // Used attach/detach to subscribe.
    template <class PubT, class SubT>
    class GenSubBase<PubT, SubT, sizeof(attach)> : public SubT
    {
    protected:
    GenSubBase( PubT& publisher ): publisher_( publisher )
    { publisher_.attach( *this ); }
    virtual ~GenSubBase()
    { publisher_.detach( *this ); }
    private:
    PubT* publisher_;
    };

    }//end namespace GenSubPriv

    //
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
    // Author : werasmus
    // Date : Sep 22, 2007 7:41:39 PM
    // Description:
    // This class provides the ability to subscribe/unsubscribe in a RAII
    fashion.
    // Currently it caters for the publisher to outlive the subscriber,
    hence the
    // publisher is accepted as reference in the constructor.
    // Note:
    // Currently works for Publishers with interface <add/remove>, <attach/
    detach> and
    // <subscribe/unsubscribe>.
    // TODO:
    // We could modify the publisher member iaw. a policy at later stage,
    the default
    // probably being weak pointer.
    //
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
    template <class PubT, class SubT>
    class GenSubscriber
    : public GenSubPriv::GenSubBase<PubT,
    SubT,sizeof(GenSubPriv::get_method_literal<PubT>(0))>
    {
    protected:
    typedef typename GenSubPriv::GenSubBase<PubT,
    SubT,sizeof(GenSubPriv::get_method_literal<PubT>(0))> Base;
    //_____________ operations _____________//
    GenSubscriber( PubT& publisher ): Base( publisher ){ }
    };
     
    werasm, Sep 24, 2007
    #3
  4. Gianni Mariani

    James Kanze Guest

    On Sep 24, 12:17 am, Gianni Mariani <> wrote:
    > Two issues here:


    > a) What is the accepted definition of "observer pattern".
    > While I can't point to anything specific, I do remember having
    > issues with inconsistency in the definition.


    I don't know if there is anything really formal, but I'd tend to
    go with the description in the GoF book, if only because it
    seems to be the most widespread.

    > b) Generic observer design in C++. I have been pushing the Austria
    > "Twin" interface for a while and more recently the multi threaded
    > version of it "TwinMT" (see the 6129 alpha on sourceforge)


    I'm not sure, but "Twin" sounds like you're managing a
    one-to-one relationship. In my experience, it's almost always a
    1->n relationship: each Observable will have many Observer.

    > I am trying to distill the "fundamental" hard problems in
    > software development, especially regarding C++ and I've seen
    > too many issues relating to the observer pattern I think it is
    > elevated to "fundamental".


    > By fundamental issues I mean, "avoiding deadlock conditions",
    > object lifetime management etc.


    And persistency?

    You're not the first. Back in the early 1990's, there was a lot
    of discussion of "relationship management", with the hope of
    finding some nice generic solution. As far as I know, there
    were no real useful results, but the issue still seems to be
    considered important---Java's hyping "container-managed
    relations" in EJB.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 24, 2007
    #4
  5. On 2007-09-24 00:17, Gianni Mariani wrote:
    > Two issues here:
    >
    > a) What is the accepted definition of "observer pattern". While I can't
    > point to anything specific, I do remember having issues with
    > inconsistency in the definition.


    I would assume that it is the one given in the GoF book, if you do not
    have it the wikipedia article is more or less a copy from the book,
    especially the "Participant classes" section.

    > b) Generic observer design in C++. I have been pushing the Austria
    > "Twin" interface for a while and more recently the multi threaded
    > version of it "TwinMT" (see the 6129 alpha on sourceforge)
    >
    > I am trying to distill the "fundamental" hard problems in software
    > development, especially regarding C++ and I've seen too many issues
    > relating to the observer pattern I think it is elevated to "fundamental".


    I do not see how there can any issues with the observer pattern, it is
    very simple, however I perhaps not very useful either. I prefer a more
    advanced version (I am sure this is some pattern but I do not know its
    name) where the observing class is not only informed that something has
    happened, but also what. So instead of just having a notify() function
    the observing class has a onFoo(Bar& sender, FooArgs arguments) function
    that tells the observing class what happened (the arguments) and to whom
    (the sender). Anyone know the name of this pattern?

    --
    Erik Wikström
     
    =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=, Sep 24, 2007
    #5
  6. Gianni Mariani

    werasm Guest

    Erik Wikström wrote:

    not see how there can any issues with the observer pattern, it is
    > very simple, however I perhaps not very useful either. I prefer a more
    > advanced version (I am sure this is some pattern but I do not know its
    > name) where the observing class is not only informed that something has
    > happened, but also what. So instead of just having a notify() function
    > the observing class has a onFoo(Bar& sender, FooArgs arguments) function
    > that tells the observing class what happened (the arguments) and to whom
    > (the sender). Anyone know the name of this pattern?


    Aspect observer, perhaps? Notify( aspect) or Notify( state ). But
    our observers only tend to observer a very concise aspect. One
    could register for notification wrt. a particular concern or aspect.

    Register: Observer. // where the observer has interface GetAspect.
     
    werasm, Sep 24, 2007
    #6
    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. Beatrice Rutger
    Replies:
    0
    Views:
    728
    Beatrice Rutger
    Jun 5, 2005
  2. Replies:
    6
    Views:
    743
    Chris Uppal
    Feb 13, 2006
  3. mem

    Observer pattern

    mem, May 18, 2004, in forum: C++
    Replies:
    2
    Views:
    536
    adiian
    Jun 4, 2007
  4. Paolino

    An observer pattern application.

    Paolino, Aug 18, 2005, in forum: Python
    Replies:
    0
    Views:
    340
    Paolino
    Aug 18, 2005
  5. Brian Palmer
    Replies:
    6
    Views:
    174
    Joel VanderWerf
    Aug 18, 2004
Loading...

Share This Page