[gjs] Use a GTypeModule for registering custom types



commit 235a3c0508c90ab31e8d56aed9e4695050247e59
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Wed Jul 4 22:25:57 2012 +0200

    Use a GTypeModule for registering custom types
    
    This makes so that the types are installed as dynamic types, and
    thus loaded and unloaded on demand. In particular, resources such
    as signal class closures are now properly released when the use count
    of these types drops to zero.
    Additionally, to avoid unloading too early, each GObject prototype
    has a now a reference on the GObjectClass. This means that the above
    only applies at context destruction, and preserves previous semantics
    wrt property and signal installation.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=679688

 Makefile.am       |    2 +
 gi/object.c       |   27 +++++++++++++-----
 gjs/type-module.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 gjs/type-module.h |   43 ++++++++++++++++++++++++++++++
 4 files changed, 139 insertions(+), 8 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 648b57f..d532973 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,6 +37,7 @@ nobase_gjs_module_include_HEADERS =	\
 	gjs/byteArray.h		\
 	gjs/importer.h		\
 	gjs/jsapi-util.h	\
+	gjs/type-module.h	\
 	gjs/mem.h		\
 	gjs/native.h	\
 	gi/ns.h	        \
@@ -114,6 +115,7 @@ libgjs_la_SOURCES =		\
 	gjs/native.c		\
 	gjs/profiler.c		\
 	gjs/stack.c		\
+	gjs/type-module.c	\
 	gjs/unit-test-utils.c	\
 	util/error.c		\
 	util/glib.c		\
diff --git a/gi/object.c b/gi/object.c
index d9cfb68..f4d5e26 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -39,6 +39,7 @@
 
 #include <gjs/gjs-module.h>
 #include <gjs/compat.h>
+#include <gjs/type-module.h>
 
 #include <util/log.h>
 
@@ -54,6 +55,10 @@ typedef struct {
 
     /* a list of all signal connections, used when tracing */
     GList *signals;
+
+    /* the GObjectClass wrapped by this JS Object (only used for
+       prototypes) */
+    GTypeClass *klass;
 } ObjectInstance;
 
 typedef struct {
@@ -1118,6 +1123,11 @@ object_instance_finalize(JSContext *context,
         priv->info = NULL;
     }
 
+    if (priv->klass) {
+        g_type_class_unref (priv->klass);
+        priv->klass = NULL;
+    }
+
     GJS_DEC_COUNTER(object);
     g_slice_free(ObjectInstance, priv);
 }
@@ -1722,6 +1732,7 @@ gjs_define_object_class(JSContext     *context,
     if (info)
         g_base_info_ref( (GIBaseInfo*) priv->info);
     priv->gtype = gtype;
+    priv->klass = g_type_class_ref (gtype);
     JS_SetPrivate(context, prototype, priv);
 
     gjs_debug(GJS_DEBUG_GOBJECT, "Defined class %s prototype %p class %p in object %p",
@@ -2193,6 +2204,7 @@ gjs_register_type(JSContext *cx,
     JSObject *parent, *constructor;
     GType instance_type, parent_type;
     GTypeQuery query;
+    GTypeModule *type_module;
     ObjectInstance *parent_priv;
     GTypeInfo type_info = {
         0, /* class_size */
@@ -2231,10 +2243,12 @@ gjs_register_type(JSContext *cx,
     type_info.class_size = query.class_size;
     type_info.instance_size = query.instance_size;
 
-    instance_type = g_type_register_static(parent_type,
-                                           name,
-                                           &type_info,
-                                           0);
+    type_module = G_TYPE_MODULE (gjs_type_module_get());
+    instance_type = g_type_module_register_type(type_module,
+                                                parent_type,
+                                                name,
+                                                &type_info,
+                                                0);
 
     g_free(name);
 
@@ -2287,7 +2301,6 @@ gjs_register_property(JSContext *cx,
     JSObject *pspec_js;
     GParamSpec *pspec;
     ObjectInstance *priv;
-    GObjectClass *oclass;
 
     if (argc != 2)
         return JS_FALSE;
@@ -2304,9 +2317,7 @@ gjs_register_property(JSContext *cx,
 
     g_param_spec_set_qdata(pspec, gjs_is_custom_property_quark(), GINT_TO_POINTER(1));
 
-    oclass = g_type_class_ref(priv->gtype);
-    g_object_class_install_property(oclass, PROP_JS_HANDLED, pspec);
-    g_type_class_unref(oclass);
+    g_object_class_install_property(G_OBJECT_CLASS (priv->klass), PROP_JS_HANDLED, pspec);
 
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
diff --git a/gjs/type-module.c b/gjs/type-module.c
new file mode 100644
index 0000000..380c52f
--- /dev/null
+++ b/gjs/type-module.c
@@ -0,0 +1,75 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa giovanni gmail com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "type-module.h"
+
+struct _GjsTypeModule {
+    GTypeModule parent;
+};
+
+struct _GjsTypeModuleClass {
+    GTypeModuleClass parent_class;
+};
+
+G_DEFINE_TYPE (GjsTypeModule, gjs_type_module, G_TYPE_TYPE_MODULE)
+
+static GjsTypeModule *global_type_module;
+
+GjsTypeModule *
+gjs_type_module_get ()
+{
+    if (global_type_module == NULL) {
+        global_type_module = g_object_new (GJS_TYPE_TYPE_MODULE, NULL);
+    }
+
+    return global_type_module;
+}
+
+static gboolean
+gjs_type_module_load (GTypeModule *self)
+{
+    return TRUE;
+}
+
+static void
+gjs_type_module_unload (GTypeModule *self)
+{
+    g_assert_not_reached ();
+}
+
+static void
+gjs_type_module_class_init (GjsTypeModuleClass *klass)
+{
+    GTypeModuleClass *type_module_class;
+
+    type_module_class = G_TYPE_MODULE_CLASS (klass);
+    type_module_class->load = gjs_type_module_load;
+    type_module_class->unload = gjs_type_module_unload;
+}
+
+static void
+gjs_type_module_init (GjsTypeModule *self)
+{
+    /* Prevent the use count from ever dropping to zero */
+    g_type_module_use (G_TYPE_MODULE (self));
+}
diff --git a/gjs/type-module.h b/gjs/type-module.h
new file mode 100644
index 0000000..a4ea514
--- /dev/null
+++ b/gjs/type-module.h
@@ -0,0 +1,43 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa giovanni gmail com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef GJS_TYPE_MODULE_H
+#define GJS_TYPE_MODULE_H
+
+#include <glib-object.h>
+
+typedef struct _GjsTypeModule GjsTypeModule;
+typedef struct _GjsTypeModuleClass GjsTypeModuleClass;
+
+#define GJS_TYPE_TYPE_MODULE              (gjs_type_module_get_type ())
+#define GJS_TYPE_MODULE(module)           (G_TYPE_CHECK_INSTANCE_CAST ((module), GJS_TYPE_TYPE_MODULE, GjsTypeModule))
+#define GJS_TYPE_MODULE_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), GJS_TYPE_TYPE_MODULE, GjsTypeModuleClass))
+#define GJS_IS_TYPE_MODULE(module)        (G_TYPE_CHECK_INSTANCE_TYPE ((module), GJS_TYPE_TYPE_MODULE))
+#define GJS_IS_TYPE_MODULE_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), GJS_TYPE_TYPE_MODULE))
+#define GJS_TYPE_MODULE_GET_CLASS(module) (G_TYPE_INSTANCE_GET_CLASS ((module), GJS_TYPE_TYPE_MODULE, GjsTypeModuleClass))
+
+GType gjs_type_module_get_type (void) G_GNUC_CONST;
+
+GjsTypeModule *gjs_type_module_get (void);
+
+#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]