2 * Copyright (c) 2008,2009 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
23 /* GSources are tricky to bind to perl for a few reasons:
24 * - they have a one-way state machine: once attached and detached, they
25 * cannot be re-attached
26 * - different "kinds" of GSources require C-level callbacks with
27 * different signatures
28 * - an attached GSource should continue running, even if not referenced
29 * from perl, while a detached GSource should free all its resources
30 * when no longer referenced.
32 * To accomplish all of this, this file implements a "glue object" called
33 * amglue_Source. There are zero or one amglue_Source objects for each
34 * GSource object, so they serve as a place to store "extra" data about a
35 * GSource. In particular, they store:
36 * - a pointer to a C callback function that can trigger a Perl callback
37 * - a pointer to an SV representing the perl callback to run
39 * Any number of Perl SV's may reference the amglue_Source -- it tracks this
40 * via its reference count.
42 * Let's look at this arrangement as it follows a typical usage scenario. The
43 * numbers in brackets are reference counts.
45 * -- my $src = Amanda::MainLoop::new_foo_source();
46 * GSrc[1] <----) amSrc[1] <---- $src[1] <--- perl-stack
48 * The lexical $src contains a reference to the amglue_Source object, which is
49 * referencing the underlying GSource object. Pretty simple. The amglue_Source
50 * only counts one reference because the GSource isn't yet attached. Think of
51 * the ')' in the diagram as a weak reference. If the perl scope were to end
52 * now, all of these objects would be freed immediately.
54 * -- $src->set_callback(\&cb);
56 * GMainLoop --> GSrc[2] <---> amSrc[2]
57 * ^--- $src[1] <--- perl-stack
59 * The GSource has been attached, so GMainLoop holds a reference to it. The
60 * amglue_Source incremented its own reference count, making the previous weak
61 * reference a full reference, because the link from the GSource will be used
62 * when a callback occurs. The amglue_Source object also keeps a reference to
63 * the callback coderef.
67 * GMainLoop --> GSrc[2] <---> amSrc[1]
69 * When the perl scope ends, the lexical $src is freed, reducing the reference
70 * count on the amglue_Source to 1. At this point, the object is not accessible
71 * from perl, but it is still accessible from the GSource via a callback.
75 * GMainLoop --> GSrc[2] <---> amSrc[2] <--- $self[1] <--- perl-stack
77 * When the callback is invoked, a reference to the amglue_Source is placed on
78 * the perl stack, so it is once again referenced twice.
81 * GSrc[1] <---) amSrc[1] <--- $self[1] <--- perl-stack
83 * Now the callback itself has called remove(). The amglue_Source object removes
84 * the GSource from the MainLoop and drops its reference to the perl callback, and
85 * decrements its refcount to again weaken the reference from the GSource. The
86 * amglue_Source is now useless, but since it is still in scope, it remains
87 * allocated and accessible.
91 * When the callback returns, the last reference to SV is destroyed, reducing
92 * the reference count to the amglue_Source to zero, reducing the reference to
93 * the GSource to zero. Everything is gone.
96 /* We use a glib 'dataset' to attach an amglue_Source to each GSource
97 * object. This requires a Quark to describe the kind of data being
100 * We define a macro and corresponding global to support access
101 * to our quark. The compiler will optimize out all but the first
102 * conditional in each function, which is just as we want it. */
103 static GQuark _quark = 0;
104 #define AMGLUE_SOURCE_QUARK \
105 ( _quark?_quark:(_quark = g_quark_from_static_string("amglue_Source")) )
110 GSourceFunc callback)
113 g_assert(gsrc != NULL);
115 src = (amglue_Source *)g_dataset_id_get_data(gsrc, AMGLUE_SOURCE_QUARK);
118 src = amglue_source_new(gsrc, callback);
120 amglue_source_ref(src);
128 GSourceFunc callback)
130 amglue_Source *src = g_new0(amglue_Source, 1);
133 src->callback = callback;
134 src->state = AMGLUE_SOURCE_NEW;
136 g_dataset_id_set_data(gsrc, AMGLUE_SOURCE_QUARK, (gpointer)src);
145 /* if we're attached, we hold a circular reference to ourselves,
146 * so we shouldn't be at refcount=0 */
147 g_assert(self->state != AMGLUE_SOURCE_ATTACHED);
148 g_assert(self->callback_sv == NULL);
150 g_dataset_id_remove_data(self->src, AMGLUE_SOURCE_QUARK);
151 g_source_unref(self->src);