callback arguments and installation
- From: Tim Janik <timj imendio com>
- To: Kristian Rietveld <kris imendio com>, Federico Mena Quintero <federico ximian com>
- Cc: Gtk+ Developers <gtk-devel-list gnome org>
- Subject: callback arguments and installation
- Date: Thu, 23 Feb 2006 15:54:05 +0100 (CET)
hi,
from http://www.gtk.org/plan/meetings/20060222.txt:
Feb 22 16:27:14 <federico> in gtkfilesystemunix
Feb 22 16:27:31 <federico> you have dispatch_get_info_callback(), where the caller must *not* free the file_info
Feb 22 16:27:49 <federico> you have dispatch_get_folder_callback(), where the caller *must* unref the folder object
Feb 22 16:28:16 <federico> I don't like that disparity. All such functions should give the caller's callback something that it *must* unref/free.
Feb 22 16:28:55 <federico> mclasen: so that we can ref a single instance of each icon instead of having many copies
Feb 22 16:29:18 <kris> hrm, I think it makes more sense that the dispatch routine would unref/free all stuff it passed to the callback when the callback returns
Feb 22 16:29:29 <kris> and if the receiver of the callback wants to use that data later on it would ref/copy it
Feb 22 16:30:53 <kris> but we probably need to match here what the rest of gtk+ does
Feb 22 16:33:30 <federico> kris: that's another possibility. In any case, it should be consistent across callbacks.
Feb 22 16:33:43 <kris> yep
*the* gtk example for this are signal callbacks. in general, if callbacks are
invoked, all arguments/obejcts/handles passed in to it should be kept alive
across the whole invocation. e.g.:
/* make sure all args stay alive and const across callback invocation */
char *x= g_strdup (volatile_string);
GObject *o = g_object_ref (something);
callback (x, o);
g_free (x);
g_object_unref (o);
as a related side note, depending on the API, extra provisions have to
be taken to handle callback modification/removal calls during callback
invocation.
e.g. this code is buggy:
void
foo_set_callback (Foo *f,
FooFunc ffunc,
gpointer data,
GDestroyFunc dfunc)
{
if (f->dfunc)
f->dfunc (f->data); /* BAD: callback called with f->dfunc containing old pointer */
f->ffunc = ffunc;
f->data = data;
f->dfunc = dfunc;
}
because the invocation of f->dfunc() might call foo_set_callback() again
(not unlikely, especially if f->dfunc() calls library routines that have
their own cleanup routines, do unref()s, etc.)
instead, the following logic should be used:
void
foo_set_callback (Foo *f,
FooFunc ffunc,
gpointer data,
GDestroyFunc dfunc)
{
GDestroyFunc odestroy = f->dfunc;
gpointer odata = f->data;
f->ffunc = ffunc;
f->data = data;
f->dfunc = dfunc;
if (odestroy)
odestroy (odata); /* GOOD: foo_set_callback() may safely be called recursively */
}
---
ciaoTJ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]