Stale object pointers in an event queue

Discussion in 'C++' started by Kenneth Porter, May 4, 2011.

  1. I register with an external API to get callbacks upon physical events. The
    events are queued and my generic callback is invoked from the API's thread.
    I can pass a "context" to be included with the callback parameters.

    I pass a pointer to my handler object and, when the generic callback is
    invoked, I cast the pointer to the object and invoke it's handle() method.

    The problem is that when I de-register interest in the events, the API is
    documented to continue to call my callback until its queue is empty. That
    means I don't know when it's safe to delete my handler objects. I need some
    way to validate the context values passed to my generic handler before
    using them as object pointers.

    How do others handle this situation?


    Some things I've considered:

    Keep a magic number in my objects that I check for to see if the object
    pointer is valid. Trash the magic number when the object is destroyed.

    Keep a bag of valid object pointers and make sure the supplied context
    pointer is in the bag before I use it.

    If an object is deleted and another is created that happens to get the same
    address, it might start getting events intended for the old object. I might
    need to tag my objects with some kind of unique ID and use a hash of the
    object as my event context, keeping a map between hashes and objects.
    Kenneth Porter, May 4, 2011
    #1
    1. Advertising

  2. Kenneth Porter

    gwowen Guest

    On May 4, 3:28 am, Kenneth Porter <>
    wrote:
    > How do others handle this situation?


    If the problem is that the you want to dispose of handler objects in a
    timely fashion, you can add another layer of indirection - instead of
    passing the object pointer, you could pass a pointer to the pointer,
    and set that to NULL prior to disposing of the handler (or use
    boost::fallible). Then the callback can check if the handler still
    exists.
    gwowen, May 4, 2011
    #2
    1. Advertising

  3. Kenneth Porter

    Jorgen Grahn Guest

    On Wed, 2011-05-04, Kenneth Porter wrote:
    > I register with an external API to get callbacks upon physical events. The
    > events are queued and my generic callback is invoked from the API's thread.
    > I can pass a "context" to be included with the callback parameters.
    >
    > I pass a pointer to my handler object and, when the generic callback is
    > invoked, I cast the pointer to the object and invoke it's handle() method.
    >
    > The problem is that when I de-register interest in the events, the API is
    > documented to continue to call my callback until its queue is empty.


    Sounds like you should submit a bug report -- those semantics seem
    suboptimal. (Although perhaps the threading makes that necessary?)

    > That
    > means I don't know when it's safe to delete my handler objects. I need some
    > way to validate the context values passed to my generic handler before
    > using them as object pointers.
    >
    > How do others handle this situation?
    >
    >
    > Some things I've considered:
    >
    > Keep a magic number in my objects that I check for to see if the object
    > pointer is valid. Trash the magic number when the object is destroyed.
    >
    > Keep a bag of valid object pointers and make sure the supplied context
    > pointer is in the bag before I use it.
    >
    > If an object is deleted and another is created that happens to get the same
    > address, it might start getting events intended for the old object. I might
    > need to tag my objects with some kind of unique ID and use a hash of the
    > object as my event context, keeping a map between hashes and objects.


    How about not unregistering, but re-registering with a "bitbucket"
    callback instead?

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, May 4, 2011
    #3
  4. Kenneth Porter

    samjam86 Guest

    On May 4, 3:25 pm, Jorgen Grahn <> wrote:
    > On Wed, 2011-05-04, Kenneth Porter wrote:
    > > I register with an external API to get callbacks upon physical events. The
    > > events are queued and my generic callback is invoked from the API's thread.
    > > I can pass a "context" to be included with the callback parameters.

    >
    > > I pass a pointer to my handler object and, when the generic callback is
    > > invoked, I cast the pointer to the object and invoke it's handle() method.

    >
    > > The problem is that when I de-register interest in the events, the API is
    > > documented to continue to call my callback until its queue is empty.

    >
    > Sounds like you should submit a bug report -- those semantics seem
    > suboptimal. (Although perhaps the threading makes that necessary?)
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > That
    > > means I don't know when it's safe to delete my handler objects. I need some
    > > way to validate the context values passed to my generic handler before
    > > using them as object pointers.

    >
    > > How do others handle this situation?

    >
    > > Some things I've considered:

    >
    > > Keep a magic number in my objects that I check for to see if the object
    > > pointer is valid. Trash the magic number when the object is destroyed.

    >
    > > Keep a bag of valid object pointers and make sure the supplied context
    > > pointer is in the bag before I use it.

    >
    > > If an object is deleted and another is created that happens to get the same
    > > address, it might start getting events intended for the old object. I might
    > > need to tag my objects with some kind of unique ID and use a hash of the
    > > object as my event context, keeping a map between hashes and objects.

    >
    > How about not unregistering, but re-registering with a "bitbucket"
    > callback instead?
    >
    > /Jorgen
    >
    > --
    >   // Jorgen Grahn <grahn@  Oo  o.   .  .
    > \X/     snipabacken.se>   O  o   .


    Normally a good library provides you a number of options in this case.
    The one I can think of immediately are:

    a. Library provides a way to unregister. (as Jorgen also mentioned)
    b. We create the queue and attach it on dispatcher(external API) along
    with our subscription request i.e. in this case the
    dispatcher(external API) and queue are both under our control. And we
    can deactivate/destroy the queue and then unregister ourselves on
    dispatcher. In this way once the queue is deactivated no more
    callbacks will be queued and you are safe to deregister.

    Is there any way you turn on the queue yourself or it is the only
    option? Do you have access to get the size of the queue? How do you
    say that now I want to get callbacks on a new object?
    samjam86, May 4, 2011
    #4
  5. Jorgen Grahn <> wrote in
    news::

    > How about not unregistering, but re-registering with a "bitbucket"
    > callback instead?


    The registration is actually across a communication medium, so re-
    registering would leave the cost of an event stream in place when it was no
    longer needed, tying up scarce bandwidth useful for other purposes.
    Kenneth Porter, May 6, 2011
    #5
  6. samjam86 <> wrote in news:9ab32ac7-dcbd-4c71-8480-
    :

    > Normally a good library provides you a number of options in this case.
    > The one I can think of immediately are:
    >
    > a. Library provides a way to unregister. (as Jorgen also mentioned)
    > b. We create the queue and attach it on dispatcher(external API) along
    > with our subscription request i.e. in this case the
    > dispatcher(external API) and queue are both under our control. And we
    > can deactivate/destroy the queue and then unregister ourselves on
    > dispatcher. In this way once the queue is deactivated no more
    > callbacks will be queued and you are safe to deregister.
    >
    > Is there any way you turn on the queue yourself or it is the only
    > option? Do you have access to get the size of the queue? How do you
    > say that now I want to get callbacks on a new object?


    The API has a define/delete pair to associate a handler with an event ID.
    Apparently there's a single queue that all registered events pass through.

    It sounds like you're suggesting that I add my own queue downstream of the
    raw callback interface in addition to their queue that I don't have control
    over. But that does suggest another approach:

    Keep my own registration database that gets checked by my generic handler
    before passing the call through to my real handler objects. I can use a key
    of the event ID appended to the context value treated as a simple 32-bit
    counter. (Allocating 4 billion handlers over the life of the application
    isn't likely.)
    Kenneth Porter, May 6, 2011
    #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. Jeff Nokes

    Cache::Cache Stale Segments

    Jeff Nokes, Sep 30, 2003, in forum: Perl
    Replies:
    0
    Views:
    555
    Jeff Nokes
    Sep 30, 2003
  2. John Rivers

    Stale Forms

    John Rivers, Sep 2, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    542
    Tim_Mac
    Sep 7, 2005
  3. Russell Warren

    Is Queue.Queue.queue.clear() thread-safe?

    Russell Warren, Jun 22, 2006, in forum: Python
    Replies:
    4
    Views:
    662
    Russell Warren
    Jun 27, 2006
  4. Kris
    Replies:
    0
    Views:
    461
  5. John Honovich

    Stale ActiveRecord Object

    John Honovich, Mar 23, 2008, in forum: Ruby
    Replies:
    1
    Views:
    92
    Mark Bush
    Mar 23, 2008
Loading...

Share This Page