Stale object pointers in an event queue

K

Kenneth Porter

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.
 
G

gwowen

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.
 
J

Jorgen Grahn

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
 
S

samjam86

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















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

/Jorgen

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?
 
K

Kenneth Porter

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.
 
K

Kenneth Porter

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.)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top