Discussion:
[Audiere-users] callbacks
Jonathan Mcdougall
2005-10-12 21:27:10 UTC
Permalink
Devices store callbacks in a vector or CallbackPtr. This means they
take ownership of the memory (this is nowhere stated, it should be).

Since unregisterCallback() does not return the object, it is
automatically destroyed when unregistered. Also, because
registerCallback() takes a plain pointer, it is impossible to share
the ref-counted pointer in the vector.

Because of this, it is impossible to own the object after it has been
added to the device. This causes me a problem because my callback may
be expensive to create and I frequently register and unregister it. I
need to be able to reuse the pointer.

I can see three solutions:

1) make unregisterCallback() return the removed pointer (by a plain
pointer or, better, by a CallbackPtr)
2) make registerCallback() take a CallbackPtr which will only
increases the reference count
3) store the pointers as plain and delete them in the dtor

Number 1) makes it assymetric with clearCallbacks(), which is why I
think 2) would be better. Functionnaly, 2) and 3) are identical, but
2) is safer.


Jonathan
Chad Austin
2005-10-13 03:36:46 UTC
Permalink
Hi Jonathan,

Callbacks are refcounted, so you can share ownership. CallbackPtr is a
refcounting smart pointer. Do something like:

class MyCallback : public RefImplementation<Callback> {
...
}

{
CallbackPtr myHandle(new MyCallback); // refcount = 1

device->registerCallback(myHandle.get()) // refcount = 2
device->unregisterCallback(myHandle.get()) // refcount = 1

// use myHandle however. still alive, since refcount = 1
} // scope ends -> destroying myHandle pointer -> refcount = 0 -> callback is
destroyed.

HTH,
Chad
Post by Jonathan Mcdougall
Devices store callbacks in a vector or CallbackPtr. This means they
take ownership of the memory (this is nowhere stated, it should be).
Since unregisterCallback() does not return the object, it is
automatically destroyed when unregistered. Also, because
registerCallback() takes a plain pointer, it is impossible to share
the ref-counted pointer in the vector.
Because of this, it is impossible to own the object after it has been
added to the device. This causes me a problem because my callback may
be expensive to create and I frequently register and unregister it. I
need to be able to reuse the pointer.
1) make unregisterCallback() return the removed pointer (by a plain
pointer or, better, by a CallbackPtr)
2) make registerCallback() take a CallbackPtr which will only
increases the reference count
3) store the pointers as plain and delete them in the dtor
Number 1) makes it assymetric with clearCallbacks(), which is why I
think 2) would be better. Functionnaly, 2) and 3) are identical, but
2) is safer.
Jonathan
-------------------------------------------------------
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
Audiere-users mailing list
https://lists.sourceforge.net/lists/listinfo/audiere-users
Jonathan Mcdougall
2005-10-14 00:38:45 UTC
Permalink
Post by Chad Austin
Hi Jonathan,
Callbacks are refcounted, so you can share ownership. CallbackPtr is a
I didn't look enough at the code, sorry.

Just for the record, by deriving from RefImplementation, you get
*intrusive* ref counting. So passing around the object is enough, as
long as it gets wrapped in a RefPtr<> eventually. But to make that
work, you have to store your own copy in a RefPtr<> or to increase the
ref count manually.

class sc : public audiere::RefImplementation<audiere::StopCallback>
{
// ...
};

void f(audiere::AudioDevicePtr dev)
{
// --- BAD
sc *c = new sc;

dev->registerCallback(c);
dev->unregisterCallback(c); // c got deleted

// ------ OK
RefPtr<sc> c(new sc);

dev->registerCallback(c);
dev->unregisterCallback(c); // c still alive


// ------ OK
sc *c = new sc;
c->ref();

dev->registerCallback(c);
dev->unregisterCallback(c); // c still alive

c->unref();
}


Jonathan

Loading...