Next: Concept Index, Previous: Example Programs, Up: Top
GObject
Objects of type GObject
and its subclasses are wrapped using a
gtkobj
smob. This smob is called the proxy for the object. It holds
the C pointer and it adds 1 to the reference count of the object. The proxy
is kept alive as long as the object exists. When the proxy is no longer used
from Scheme, and the object is also unused from anywhere in Gtk, then the
proxy and object are destroyed together.
The proxy keeps a list of “protects” which are Scheme procedures installed
as callbacks by gtk-signal-connect
etc. Those protects are kept alive
as long as the object lives but of course they're not themselves a reason to
keep the object alive, an object with callbacks can still be garbage
collected. A similar global list of protects is used for callbacks on global
things like like gtk-timeout-add
.
Some care must be taken with garbage collection. Objects in use from Scheme
variables etc are marked in the usual way, and then for GtkContainer
widgets marking recurses through the children too (any with proxies). Proxied
objects still in use from Gtk C code are then identified by looking at their
reference counts. A count of more than the 1 which the proxy puts plus
another 1 if it's in a proxied container means that somebody somewhere is
holding a reference to the object in a way that Guile-Gtk's marking has not
traversed. Such a reference is called “external” and objects with external
references are marked (and thus kept alive).
It might be wondered if just waiting for an object to have a reference count of 1 (its proxy) would be enough to know it can be garbage collected (when unreachable from Scheme). In such a system a container with refcount 1 would be collected, and then on the next GC its children would be down to a count of 1 to be collected too. But attached signal handler procedures can stop that from working. Consider container C holding widget W, and a Scheme code signal handler H connected to W and which acts on C. W has a refcount 2 and would be kept alive, so its handler H must be kept, and H refers to C, so C is kept, ie. none of the three is ever collected. The key is that refcount 2 is not in fact an absolute reason to keep W alive, rather it's a reference from C and so ought to depend on whether C is to be kept. Circular references like this occur all the time in Lisp and the way to treat them is to let marking recurse through all genuinely wanted objects, leaving unwanted objects all collected together, no matter what clusters of possibly circular references they might have between themselves.
Strictly speaking to be completely safe against circular references Guile-Gtk
would have to know and follow all references Glib and Gtk establish between
objects. But in practice just GtkContainer
children is enough, because
Gtk's references normally form a tree, it's only Scheme signal handlers
referring up to parent container widgets which create cycles.
Objects which are not sub-classes of GObject
are handled by a simpler
“boxing” system. This includes resources like GdkCursor
, and types
that are more or less user-level structures like GdkRegion
.
A gtkboxed
smob holds the C pointer to the object plus its type in the
form of an index into the Guile-Gtk type_info_tab
table. That table
holds the GType
value plus certain other information.
Boxed types each have their own specific ref
/unref
functions,
declared explicitly in the .defs file, such as gdk_cursor_ref
.
When a smob is created a reference is added, so the object stays alive while
in use from Scheme. When the smob is garbage collected, the unref function is
called. Because there's no signal handlers attached to boxed objects the
circular references problem for GObject
above doesn't occur.
In the current code, whenever a boxed type is returned a new smob is created
for it. No attempt is made to find and re-use an existing smob holding the
same pointer (and type). This is simple, but it's also the reason boxed types
can't be compared with eq?
. A smob “equalp
” function could
compare pointers, but it's not clear if that would be the best thing.
equal?
normally looks into the contents of objects, so one might want
it for instance to test whether two GdkRegion
s are the same area, or
something like that, instead of only the same object.
GType
GType
s are represented by a smob holding the GType
value (an
integer, though actually it's a pointer Glib has converted to an integer).
GType
values are never destroyed, so there's no ref/unref to apply. A
new smob is created whenever a GType
is returned, no attempt is made to
find and re-use an existing smob for it. A smob equality function allows
types to be compared with equal?
.
Guile-Gtk functions taking a GType
also accept a Scheme symbol, with
the name looked up to get the actual GType
value to pass down to C.
g_type_from_name
gives types which have been initialized (or are
builtin), and in addition Guile-Gtk has a table of get_type
functions
to call, such as gtk_vbox_get_type
for GtkVBox
. But that table
is limited to the types appearing in the .defs files, there's nowhere
in Glib or Gtk recording the names of all initializable types and classes.