Re: [PATCH] g_type_default_interface_ref(), etc.
- From: Owen Taylor <otaylor redhat com>
- To: timj gtk org
- Cc: gtk-devel-list gnome org
- Subject: Re: [PATCH] g_type_default_interface_ref(), etc.
- Date: Thu, 25 Sep 2003 17:30:05 -0400
On Thu, 2003-09-25 at 17:25, Owen Taylor wrote:
> Here's a patch for:
>
> g_type_default_interface_ref()
> g_type_default_interface_peek()
> g_type_default_interface_unref()
>
> as described in your last mail, with docs and a test case
> for both static and dynamic interfaces.
And the patch...
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/glib/ChangeLog,v
retrieving revision 1.1405
diff -u -p -u -r1.1405 ChangeLog
--- ChangeLog 25 Sep 2003 19:01:54 -0000 1.1405
+++ ChangeLog 25 Sep 2003 21:22:30 -0000
@@ -1,3 +1,9 @@
+Thu Sep 25 15:43:08 2003 Owen Taylor <otaylor redhat com>
+
+ * tests/gobject/testmodule.[ch] test/gobject/Makefile.am:
+ Dummy dynamic type module for testing type plugin code
+ and dynamic types.
+
Thu Sep 25 15:01:37 2003 Owen Taylor <otaylor redhat com>
* tests/Makefile.am (SUBDIRS): Add gobject/.
Index: docs/reference/glib/tmpl/threads.sgml
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/tmpl/threads.sgml,v
retrieving revision 1.41
diff -u -p -u -r1.41 threads.sgml
--- docs/reference/glib/tmpl/threads.sgml 30 Jul 2003 22:31:23 -0000 1.41
+++ docs/reference/glib/tmpl/threads.sgml 25 Sep 2003 21:22:30 -0000
@@ -1613,9 +1613,6 @@ Any one-time initialization function mus
struct.
</para>
- status: the status of the function controled by this struct
- retval: the return value of the function controled by this struct. This field will be
- %NULL unless <literal>status == G_ONCE_STATUS_READY</literal>.
@Since: 2.4
<!-- ##### ENUM GOnceStatus ##### -->
Index: docs/reference/gobject/gobject-sections.txt
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/gobject/gobject-sections.txt,v
retrieving revision 1.27
diff -u -p -u -r1.27 gobject-sections.txt
--- docs/reference/gobject/gobject-sections.txt 12 Sep 2003 20:37:29 -0000 1.27
+++ docs/reference/gobject/gobject-sections.txt 25 Sep 2003 21:22:30 -0000
@@ -56,6 +56,9 @@ g_type_class_peek_parent
g_type_class_add_private
g_type_interface_peek
g_type_interface_peek_parent
+g_type_default_interface_ref
+g_type_default_interface_peek
+g_type_default_interface_unref
g_type_children
g_type_interfaces
g_type_interface_prerequisites
Index: docs/reference/gobject/tmpl/gtype.sgml
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/gobject/tmpl/gtype.sgml,v
retrieving revision 1.24
diff -u -p -u -r1.24 gtype.sgml
--- docs/reference/gobject/tmpl/gtype.sgml 2 Sep 2003 17:57:21 -0000 1.24
+++ docs/reference/gobject/tmpl/gtype.sgml 25 Sep 2003 21:22:30 -0000
@@ -774,6 +774,50 @@ then possibly overriding some methods.
doesn't conform to the interface.
+<!-- ##### FUNCTION g_type_default_interface_ref ##### -->
+<para>
+Increments the reference count for the interface type @g_type,
+and returns the default interface vtable for the type.
+</para>
+<para>
+If the type is not currently in use, then the default vtable
+for the type will be created and initalized by calling
+the default vtable init and base interface init functions for
+the type (the <structfield>class_init</structfield>,
+and <structfield>base_init</structfield> members of #GTypeInfo).
+Calling g_type_default_interface_ref() is useful when you
+want to make sure that signals and properties for an interface
+have been installed.
+</para>
+
+ g_type: an interface type
+ Returns: the default vtable for the interface; call
+ g_type_default_interface_unref() when you are done using
+ the interface.
+
+<!-- ##### FUNCTION g_type_default_interface_peek ##### -->
+<para>
+If the interface type @g_type is currently in use, returns
+its default interface vtable.
+</para>
+
+ g_type: an interface type
+ Returns: the default vtable for the interface; or %NULL
+ if the type is not currently in use.
+
+<!-- ##### FUNCTION g_type_default_interface_unref ##### -->
+<para>
+Decrements the reference count for the type corresponding to the
+interface default vtable @g_iface. If the type is dynamic, then
+when no one is using the interface and all references have
+been released, the finalize function for the interface's default
+vtable (the <structfield>class_finalize</structfield> member of
+#GTypeInfo) will be called.
+</para>
+
+ g_iface: the default vtable structure for a interface, as
+ returned by g_type_default_interface_ref()
+
<!-- ##### FUNCTION g_type_children ##### -->
<para>
Return a newly allocated and 0-terminated array of type IDs, listing the
Index: gobject/gtype.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/gtype.c,v
retrieving revision 1.66
diff -u -p -u -r1.66 gtype.c
--- gobject/gtype.c 2 Sep 2003 17:57:22 -0000 1.66
+++ gobject/gtype.c 25 Sep 2003 21:22:31 -0000
@@ -2486,6 +2486,69 @@ g_type_interface_peek_parent (gpointer g
return vtable;
}
+gpointer
+g_type_default_interface_ref (GType g_type)
+{
+ TypeNode *node;
+
+ G_WRITE_LOCK (&type_rw_lock);
+
+ node = lookup_type_node_I (g_type);
+ if (G_UNLIKELY (!node || !NODE_IS_IFACE (node) ||
+ (node->data && node->data->common.ref_count < 1)))
+ {
+ G_WRITE_UNLOCK (&type_rw_lock);
+ g_warning ("cannot retrieve default vtable for invalid or non-interface type '%s'",
+ type_descriptive_name_I (g_type));
+ return NULL;
+ }
+
+ type_data_ref_Wm (node);
+
+ type_iface_ensure_dflt_vtable_Wm (node);
+
+ G_WRITE_UNLOCK (&type_rw_lock);
+
+ return node->data->iface.dflt_vtable;
+}
+
+gpointer
+g_type_default_interface_peek (GType g_type)
+{
+ TypeNode *node;
+ gpointer class;
+
+ node = lookup_type_node_I (g_type);
+ G_READ_LOCK (&type_rw_lock);
+ if (node && NODE_IS_IFACE (node) && node->data && node->data->iface.dflt_vtable)
+ class = node->data->iface.dflt_vtable;
+ else
+ class = NULL;
+ G_READ_UNLOCK (&type_rw_lock);
+
+ return class;
+}
+
+void
+g_type_default_interface_unref (gpointer g_iface)
+{
+ TypeNode *node;
+ GTypeInterface *vtable = g_iface;
+
+ g_return_if_fail (g_iface != NULL);
+
+ node = lookup_type_node_I (vtable->g_type);
+ G_WRITE_LOCK (&type_rw_lock);
+ if (G_LIKELY (node && NODE_IS_IFACE (node) &&
+ node->data->iface.dflt_vtable == g_iface &&
+ node->data->common.ref_count > 0))
+ type_data_unref_Wm (node, FALSE);
+ else
+ g_warning ("cannot unreference invalid interface default vtable for '%s'",
+ type_descriptive_name_I (vtable->g_type));
+ G_WRITE_UNLOCK (&type_rw_lock);
+}
+
G_CONST_RETURN gchar*
g_type_name (GType type)
{
Index: gobject/gtype.h
===================================================================
RCS file: /cvs/gnome/glib/gobject/gtype.h,v
retrieving revision 1.49
diff -u -p -u -r1.49 gtype.h
--- gobject/gtype.h 2 Sep 2003 17:57:22 -0000 1.49
+++ gobject/gtype.h 25 Sep 2003 21:22:31 -0000
@@ -183,6 +183,10 @@ gpointer g_type_interface_p
GType iface_type);
gpointer g_type_interface_peek_parent (gpointer g_iface);
+gpointer g_type_default_interface_ref (GType g_type);
+gpointer g_type_default_interface_peek (GType g_type);
+void g_type_default_interface_unref (gpointer g_iface);
+
/* g_free() the returned arrays */
GType* g_type_children (GType type,
guint *n_children);
Index: tests/gobject/Makefile.am
===================================================================
RCS file: /cvs/gnome/glib/tests/gobject/Makefile.am,v
retrieving revision 1.1
diff -u -p -u -r1.1 Makefile.am
--- tests/gobject/Makefile.am 12 Sep 2003 20:37:09 -0000 1.1
+++ tests/gobject/Makefile.am 25 Sep 2003 21:22:31 -0000
@@ -16,7 +16,9 @@ noinst_LTLIBRARIES = libtestgobject.la
libtestgobject_la_SOURCES = \
testcommon.h \
testmarshal.h \
- testmarshal.c
+ testmarshal.c \
+ testmodule.c \
+ testmodule.h
if CROSS_COMPILING
glib_genmarshal=$(GLIB_GENMARSHAL)
@@ -44,6 +46,7 @@ LDADD = $(libgobject) libtestgobject.la
test_programs = \
accumulator \
+ defaultiface \
ifaceinit \
override
Index: tests/gobject/defaultiface.c
===================================================================
RCS file: tests/gobject/defaultiface.c
diff -N tests/gobject/defaultiface.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/gobject/defaultiface.c 25 Sep 2003 21:22:31 -0000
@@ -0,0 +1,191 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 2001, 2003 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "TestDefaultIface"
+
+#undef G_DISABLE_ASSERT
+#undef G_DISABLE_CHECKS
+#undef G_DISABLE_CAST_CHECKS
+
+#include <glib-object.h>
+
+#include "testcommon.h"
+#include "testmodule.h"
+
+/* This test tests getting the default vtable for an interface
+ * and the initialization and finalization of such default
+ * interfaces.
+ *
+ * We test this both for static and for dynamic interfaces.
+ */
+
+/**********************************************************************
+ * Static interface tests
+ **********************************************************************/
+
+typedef struct _TestStaticIfaceClass TestStaticIfaceClass;
+
+struct _TestStaticIfaceClass
+{
+ GTypeInterface base_iface;
+ guint val;
+};
+
+#define TEST_TYPE_STATIC_IFACE (test_static_iface_get_type ())
+
+static void
+test_static_iface_default_init (TestStaticIfaceClass *iface)
+{
+ iface->val = 42;
+}
+
+DEFINE_IFACE (TestStaticIface, test_static_iface,
+ NULL, test_static_iface_default_init)
+
+static void
+test_static_iface (void)
+{
+ TestStaticIfaceClass *static_iface;
+
+ /* Not loaded until we call ref for the first time */
+ static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
+ g_assert (static_iface == NULL);
+
+ /* Ref loads */
+ static_iface = g_type_default_interface_ref (TEST_TYPE_STATIC_IFACE);
+ g_assert (static_iface && static_iface->val == 42);
+
+ /* Peek then works */
+ static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
+ g_assert (static_iface && static_iface->val == 42);
+
+ /* Unref does nothing */
+ g_type_default_interface_unref (static_iface);
+
+ /* And peek still works */
+ static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
+ g_assert (static_iface && static_iface->val == 42);
+}
+
+/**********************************************************************
+ * Dynamic interface tests
+ **********************************************************************/
+
+typedef struct _TestDynamicIfaceClass TestDynamicIfaceClass;
+
+struct _TestDynamicIfaceClass
+{
+ GTypeInterface base_iface;
+ guint val;
+};
+
+static GType test_dynamic_iface_type;
+static gboolean dynamic_iface_init = FALSE;
+
+#define TEST_TYPE_DYNAMIC_IFACE (test_dynamic_iface_type)
+
+static void
+test_dynamic_iface_default_init (TestStaticIfaceClass *iface)
+{
+ dynamic_iface_init = TRUE;
+ iface->val = 42;
+}
+
+static void
+test_dynamic_iface_default_finalize (TestStaticIfaceClass *iface)
+{
+ dynamic_iface_init = FALSE;
+}
+
+static void
+test_dynamic_iface_register (GTypeModule *module)
+{
+ static const GTypeInfo iface_info =
+ {
+ sizeof (TestDynamicIfaceClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) test_dynamic_iface_default_init,
+ (GClassFinalizeFunc) test_dynamic_iface_default_finalize
+ };
+
+ test_dynamic_iface_type = g_type_module_register_type (module, G_TYPE_INTERFACE,
+ "TestDynamicIface", &iface_info, 0);
+}
+
+static void
+module_register (GTypeModule *module)
+{
+ test_dynamic_iface_register (module);
+}
+
+static void
+test_dynamic_iface (void)
+{
+ GTypeModule *module;
+ TestDynamicIfaceClass *dynamic_iface;
+
+ module = test_module_new (module_register);
+
+ /* Not loaded until we call ref for the first time */
+ dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
+ g_assert (dynamic_iface == NULL);
+
+ /* Ref loads */
+ dynamic_iface = g_type_default_interface_ref (TEST_TYPE_DYNAMIC_IFACE);
+ g_assert (dynamic_iface_init);
+ g_assert (dynamic_iface && dynamic_iface->val == 42);
+
+ /* Peek then works */
+ dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
+ g_assert (dynamic_iface && dynamic_iface->val == 42);
+
+ /* Unref causes finalize */
+ g_type_default_interface_unref (dynamic_iface);
+ g_assert (!dynamic_iface_init);
+
+ /* Peek returns NULL */
+ dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
+ g_assert (dynamic_iface == NULL);
+
+ /* Ref reloads */
+ dynamic_iface = g_type_default_interface_ref (TEST_TYPE_DYNAMIC_IFACE);
+ g_assert (dynamic_iface_init);
+ g_assert (dynamic_iface && dynamic_iface->val == 42);
+
+ /* And Unref causes finalize once more*/
+ g_type_default_interface_unref (dynamic_iface);
+ g_assert (!dynamic_iface_init);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
+ G_LOG_LEVEL_WARNING |
+ G_LOG_LEVEL_CRITICAL);
+ g_type_init ();
+
+ test_static_iface ();
+ test_dynamic_iface ();
+
+ return 0;
+}
Index: tests/gobject/testmodule.c
===================================================================
RCS file: tests/gobject/testmodule.c
diff -N tests/gobject/testmodule.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/gobject/testmodule.c 25 Sep 2003 21:22:31 -0000
@@ -0,0 +1,69 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * testmodule.c: Dummy dynamic type module
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "testmodule.h"
+#include "testcommon.h"
+
+static gboolean test_module_load (GTypeModule *module);
+static void test_module_unload (GTypeModule *module);
+
+static void
+test_module_class_init (TestModuleClass *class)
+{
+ GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
+
+ module_class->load = test_module_load;
+ module_class->unload = test_module_unload;
+}
+
+DEFINE_TYPE (TestModule, test_module,
+ test_module_class_init, NULL, NULL,
+ G_TYPE_TYPE_MODULE)
+
+static gboolean
+test_module_load (GTypeModule *module)
+{
+ TestModule *test_module = TEST_MODULE (module);
+
+ test_module->register_func (module);
+
+ return TRUE;
+}
+
+static void
+test_module_unload (GTypeModule *module)
+{
+}
+
+GTypeModule *
+test_module_new (TestModuleRegisterFunc register_func)
+{
+ TestModule *test_module = g_object_new (TEST_TYPE_MODULE, NULL);
+ GTypeModule *module = G_TYPE_MODULE (test_module);
+
+ test_module->register_func = register_func;
+
+ /* Register the types initially */
+ g_type_module_use (module);
+ g_type_module_unuse (module);
+
+ return G_TYPE_MODULE (module);
+}
+
Index: tests/gobject/testmodule.h
===================================================================
RCS file: tests/gobject/testmodule.h
diff -N tests/gobject/testmodule.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/gobject/testmodule.h 25 Sep 2003 21:22:31 -0000
@@ -0,0 +1,57 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * testmodule.h: Dummy dynamic type module
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TEST_MODULE_H__
+#define __TEST_MODULE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _TestModule TestModule;
+typedef struct _TestModuleClass TestModuleClass;
+
+#define TEST_TYPE_MODULE (test_module_get_type ())
+#define TEST_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), TEST_TYPE_MODULE, TestModule))
+#define TEST_MODULE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), TEST_TYPE_MODULE, TestModuleClass))
+#define TEST_IS_MODULE(module) (G_TYPE_CHECK_INSTANCE_TYPE ((module), TEST_TYPE_MODULE))
+#define TEST_IS_MODULE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), TEST_TYPE_MODULE))
+#define TEST_MODULE_GET_CLASS(module) (G_TYPE_INSTANCE_GET_CLASS ((module), TEST_TYPE_MODULE, TestModuleClass))
+
+typedef void (*TestModuleRegisterFunc) (GTypeModule *module);
+
+struct _TestModule
+{
+ GTypeModule parent_instance;
+
+ TestModuleRegisterFunc register_func;
+};
+
+struct _TestModuleClass
+{
+ GTypeModuleClass parent_class;
+};
+
+GType test_module_get_type (void);
+GTypeModule *test_module_new (TestModuleRegisterFunc register_func);
+
+G_END_DECLS
+
+#endif /* __TEST_MODULE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]