From: Tim Janik Date: Fri, 9 Mar 2001 14:02:30 +0000 (+0000) Subject: test program. covers run first/last/cleanup signal handlers, return value X-Git-Tag: GLIB_1_3_3~66 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=43b692c8eb49a82657d9cb09a222dc66f2cc0199;p=platform%2Fupstream%2Fglib.git test program. covers run first/last/cleanup signal handlers, return value Fri Mar 9 14:57:17 2001 Tim Janik * testgruntime.c: test program. covers run first/last/cleanup signal handlers, return value accumulator, signal string returns, and interface types in signal arguments. * gtype.c (g_type_value_table_peek): for interface types without value table, try looking up a value table from an instantiatable prerequisite type (this is safe as an interface may only have one instantiatable prerequisiste). (type_check_is_value_type_U): same here. * gsignal.c (g_signal_newv): assert that return types never have G_SIGNAL_TYPE_STATIC_SCOPE set. (g_signal_newc): only create class closure if the class_offset is not 0. --- diff --git a/gobject/ChangeLog b/gobject/ChangeLog index 309a18a..002a295 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,20 @@ +Fri Mar 9 14:57:17 2001 Tim Janik + + * testgruntime.c: test program. covers run first/last/cleanup signal + handlers, return value accumulator, signal string returns, and + interface types in signal arguments. + + * gtype.c (g_type_value_table_peek): for interface types without + value table, try looking up a value table from an instantiatable + prerequisite type (this is safe as an interface may only have + one instantiatable prerequisiste). + (type_check_is_value_type_U): same here. + + * gsignal.c (g_signal_newv): assert that return types never have + G_SIGNAL_TYPE_STATIC_SCOPE set. + (g_signal_newc): only create class closure if the class_offset is not + 0. + Fri Mar 9 10:14:00 2001 Tim Janik * gparamspecs.c (g_param_spec_object): use g_type_is_a() to check diff --git a/gobject/Makefile.am b/gobject/Makefile.am index 1005bee..fdf03bf 100644 --- a/gobject/Makefile.am +++ b/gobject/Makefile.am @@ -143,14 +143,16 @@ libgobject_1_3_la_SOURCES = $(gruntime_target_sources) # # programs to compile and install # -bin_PROGRAMS = gobject-query glib-genmarshal +bin_PROGRAMS = gobject-query glib-genmarshal testgruntime # source files gobject_query_SOURCES = gobject-query.c glib_genmarshal_SOURCES = glib-genmarshal.c +testgruntime_SOURCES = testgruntime.c # link programs against libgobject progs_LDADD = libgobject-1.3.la ../libglib-1.3.la glib_genmarshal_LDADD = ../libglib-1.3.la # can't have libgobject here gobject_query_LDADD = $(progs_LDADD) +testgruntime_LDADD = $(progs_LDADD) # # manual pages to install diff --git a/gobject/glib-genmarshal.c b/gobject/glib-genmarshal.c index 5b6b86b..fc19d17 100644 --- a/gobject/glib-genmarshal.c +++ b/gobject/glib-genmarshal.c @@ -364,7 +364,7 @@ generate_marshal (const gchar *signame, if (iarg->getter) a++; } - fprintf (fout, " g_return_if_fail (n_param_values >= %u);\n", 1 + a); + fprintf (fout, " g_return_if_fail (n_param_values == %u);\n", 1 + a); } } diff --git a/gobject/gmarshal.list b/gobject/gmarshal.list index 835fe85..9089106 100644 --- a/gobject/gmarshal.list +++ b/gobject/gmarshal.list @@ -40,6 +40,7 @@ VOID:PARAM VOID:BOXED VOID:POINTER VOID:OBJECT +STRING:OBJECT,POINTER # GRuntime specific marshallers VOID:UINT,POINTER diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 036ab4b..391b365 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -1040,7 +1040,7 @@ g_signal_newc (const gchar *signal_name, va_start (args, n_params); signal_id = g_signal_new_valist (signal_name, itype, signal_flags, - g_signal_type_cclosure_new (itype, class_offset), + class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL, accumulator, accu_data, c_marshaller, return_type, n_params, args); @@ -1069,6 +1069,7 @@ g_signal_newv (const gchar *signal_name, g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); if (n_params) g_return_val_if_fail (param_types != NULL, 0); + g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0); if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE)) g_return_val_if_fail (accumulator == NULL, 0); if (!accumulator) @@ -1885,7 +1886,7 @@ signal_emit_R (SignalNode *node, #ifdef G_ENABLE_DEBUG IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance) { - g_message ("%s::%s(%u) emitted (instance=%p signal-node=%p)\n", + g_message ("%s::%s(%u) emitted (instance=%p, signal-node=%p)", g_type_name (G_TYPE_FROM_INSTANCE (instance)), node->name, detail, instance, node); diff --git a/gobject/gtype.c b/gobject/gtype.c index 06a7303..3a181f0 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -1163,6 +1163,21 @@ g_type_interface_add_prerequisite (GType interface_type, if (prerequisite_node->is_instantiatable) { guint i; + + for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++) + { + TypeNode *prnode = lookup_type_node_L (IFACE_NODE_PREREQUISITES (iface)[i]); + + if (prnode->is_instantiatable) + { + g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'", + type_descriptive_name_L (prerequisite_type), + type_descriptive_name_L (interface_type), + type_descriptive_name_L (NODE_TYPE (prnode))); + G_WRITE_UNLOCK (&type_rw_lock); + return; + } + } for (i = 0; i < prerequisite_node->n_supers + 1; i++) type_iface_add_prerequisite_W (iface, lookup_type_node_L (prerequisite_node->supers[i])); @@ -2584,10 +2599,30 @@ type_check_is_value_type_U (GType type) TypeNode *node; G_READ_LOCK (&type_rw_lock); + restart_check: node = lookup_type_node_L (type); - if (node && node->data && node->data->common.ref_count > 0 && - node->data->common.value_table->value_init) - tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)); + if (node) + { + if (node->data && node->data->common.ref_count > 0 && + node->data->common.value_table->value_init) + tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)); + else if (NODE_IS_IFACE (node)) + { + guint i; + + for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++) + { + GType prtype = IFACE_NODE_PREREQUISITES (node)[i]; + TypeNode *prnode = lookup_type_node_L (prtype); + + if (prnode->is_instantiatable) + { + type = prtype; + goto restart_check; + } + } + } + } G_READ_UNLOCK (&type_rw_lock); return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT); @@ -2616,13 +2651,45 @@ GTypeValueTable* g_type_value_table_peek (GType type) { TypeNode *node; - GTypeValueTable *vtable = NULL; + GTypeValueTable *vtable; G_READ_LOCK (&type_rw_lock); + restart_table_peek: node = lookup_type_node_L (type); - if (node && node->data && node->data->common.ref_count > 0 && - node->data->common.value_table->value_init) + if (!node) + { + g_warning ("type id `%u' is invalid", type); + G_READ_UNLOCK (&type_rw_lock); + return NULL; + } + if (!node->data || node->data->common.ref_count < 1) + { + g_warning ("can't peek value table for type `%s' which is not currently referenced", + type_descriptive_name_L (type)); + G_READ_UNLOCK (&type_rw_lock); + return NULL; + } + if (node->data->common.value_table->value_init) vtable = node->data->common.value_table; + else if (NODE_IS_IFACE (node)) + { + guint i; + + for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++) + { + GType prtype = IFACE_NODE_PREREQUISITES (node)[i]; + TypeNode *prnode = lookup_type_node_L (prtype); + + if (prnode->is_instantiatable) + { + type = prtype; + goto restart_table_peek; + } + } + vtable = NULL; + } + else + vtable = NULL; G_READ_UNLOCK (&type_rw_lock); return vtable; diff --git a/gobject/testgobject.c b/gobject/testgobject.c new file mode 100644 index 0000000..0ccb801 --- /dev/null +++ b/gobject/testgobject.c @@ -0,0 +1,184 @@ +/* GObject - GLib Type, Object, Parameter and Signal Library + * Copyright (C) 2001 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 "TestObject" +#include + +#define TEST_TYPE_OBJECT (test_object_get_type ()) +#define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJECT, TestObject)) +#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass)) +#define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJECT)) +#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT)) +#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass)) + +typedef struct _TestIface TestIface; +typedef struct +{ + GTypeInterface base_iface; +} TestIfaceClass; +typedef struct +{ + GObject parent_instance; +} TestObject; + +#define TEST_TYPE_IFACE (test_iface_get_type ()) +#define TEST_IFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_IFACE, TestIface)) +#define TEST_IS_IFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_IFACE)) +#define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), TEST_TYPE_IFACE, TestIfaceClass)) + +GType +test_iface_get_type (void) +{ + static GType test_iface_type = 0; + + if (!test_iface_type) + { + static const GTypeInfo test_iface_info = + { + sizeof (TestIfaceClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + }; + + test_iface_type = g_type_register_static (G_TYPE_INTERFACE, "TestIface", &test_iface_info, 0); + g_type_interface_add_prerequisite (test_iface_type, G_TYPE_OBJECT); + } + + return test_iface_type; +} + +typedef struct +{ + GObjectClass parent_class; + + gchar* (*test_signal) (TestObject *tobject, + TestIface *iface_object, + gpointer tdata); +} TestObjectClass; + +static void +test_object_init (TestObject *tobject) +{ +} + +static gboolean +test_signal_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer data) +{ + gchar *accu_string = g_value_get_string (return_accu); + gchar *new_string = g_value_get_string (handler_return); + gchar *result_string; + + if (accu_string) + result_string = g_strconcat (accu_string, new_string, NULL); + else if (new_string) + result_string = g_strdup (new_string); + else + result_string = NULL; + + g_value_set_string_take_ownership (return_accu, result_string); + + return TRUE; +} + +static gchar* +test_object_test_signal (TestObject *tobject, + TestIface *iface_object, + gpointer tdata) +{ + g_message ("::test_signal default_handler called"); + + g_return_val_if_fail (TEST_IS_IFACE (iface_object), NULL); + + return g_strdup (""); +} + +static void +test_object_class_init (TestObjectClass *class) +{ + /* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */ + + class->test_signal = test_object_test_signal; + + g_signal_newc ("test-signal", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP, + G_STRUCT_OFFSET (TestObjectClass, test_signal), + test_signal_accumulator, NULL, + g_cclosure_marshal_STRING__OBJECT_POINTER, + G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER); +} + +GType +test_object_get_type (void) +{ + static GType test_object_type = 0; + + if (!test_object_type) + { + static const GTypeInfo test_object_info = + { + sizeof (TestObjectClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) test_object_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (TestObject), + 5, /* n_preallocs */ + (GInstanceInitFunc) test_object_init, + }; + GInterfaceInfo iface_info = { NULL, NULL, NULL }; + + test_object_type = g_type_register_static (G_TYPE_OBJECT, "TestObject", &test_object_info, 0); + g_type_add_interface_static (test_object_type, TEST_TYPE_IFACE, &iface_info); + } + + return test_object_type; +} + + + +int +main (int argc, + char *argv[]) +{ + TestObject *tobject, *sigarg; + gchar *string = NULL; + + 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 (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS); + + tobject = g_object_new (TEST_TYPE_OBJECT, NULL); + sigarg = g_object_new (TEST_TYPE_OBJECT, NULL); + g_signal_emit_by_name (tobject, "test-signal", sigarg, NULL, &string); + g_message ("signal return: \"%s\"", string); + g_free (string); + + g_object_unref (sigarg); + g_object_unref (tobject); + + g_message ("%s done", argv[0]); + + return 0; +} diff --git a/gobject/testgruntime.c b/gobject/testgruntime.c new file mode 100644 index 0000000..0ccb801 --- /dev/null +++ b/gobject/testgruntime.c @@ -0,0 +1,184 @@ +/* GObject - GLib Type, Object, Parameter and Signal Library + * Copyright (C) 2001 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 "TestObject" +#include + +#define TEST_TYPE_OBJECT (test_object_get_type ()) +#define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJECT, TestObject)) +#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass)) +#define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJECT)) +#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT)) +#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass)) + +typedef struct _TestIface TestIface; +typedef struct +{ + GTypeInterface base_iface; +} TestIfaceClass; +typedef struct +{ + GObject parent_instance; +} TestObject; + +#define TEST_TYPE_IFACE (test_iface_get_type ()) +#define TEST_IFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_IFACE, TestIface)) +#define TEST_IS_IFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_IFACE)) +#define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), TEST_TYPE_IFACE, TestIfaceClass)) + +GType +test_iface_get_type (void) +{ + static GType test_iface_type = 0; + + if (!test_iface_type) + { + static const GTypeInfo test_iface_info = + { + sizeof (TestIfaceClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + }; + + test_iface_type = g_type_register_static (G_TYPE_INTERFACE, "TestIface", &test_iface_info, 0); + g_type_interface_add_prerequisite (test_iface_type, G_TYPE_OBJECT); + } + + return test_iface_type; +} + +typedef struct +{ + GObjectClass parent_class; + + gchar* (*test_signal) (TestObject *tobject, + TestIface *iface_object, + gpointer tdata); +} TestObjectClass; + +static void +test_object_init (TestObject *tobject) +{ +} + +static gboolean +test_signal_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer data) +{ + gchar *accu_string = g_value_get_string (return_accu); + gchar *new_string = g_value_get_string (handler_return); + gchar *result_string; + + if (accu_string) + result_string = g_strconcat (accu_string, new_string, NULL); + else if (new_string) + result_string = g_strdup (new_string); + else + result_string = NULL; + + g_value_set_string_take_ownership (return_accu, result_string); + + return TRUE; +} + +static gchar* +test_object_test_signal (TestObject *tobject, + TestIface *iface_object, + gpointer tdata) +{ + g_message ("::test_signal default_handler called"); + + g_return_val_if_fail (TEST_IS_IFACE (iface_object), NULL); + + return g_strdup (""); +} + +static void +test_object_class_init (TestObjectClass *class) +{ + /* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */ + + class->test_signal = test_object_test_signal; + + g_signal_newc ("test-signal", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP, + G_STRUCT_OFFSET (TestObjectClass, test_signal), + test_signal_accumulator, NULL, + g_cclosure_marshal_STRING__OBJECT_POINTER, + G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER); +} + +GType +test_object_get_type (void) +{ + static GType test_object_type = 0; + + if (!test_object_type) + { + static const GTypeInfo test_object_info = + { + sizeof (TestObjectClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) test_object_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (TestObject), + 5, /* n_preallocs */ + (GInstanceInitFunc) test_object_init, + }; + GInterfaceInfo iface_info = { NULL, NULL, NULL }; + + test_object_type = g_type_register_static (G_TYPE_OBJECT, "TestObject", &test_object_info, 0); + g_type_add_interface_static (test_object_type, TEST_TYPE_IFACE, &iface_info); + } + + return test_object_type; +} + + + +int +main (int argc, + char *argv[]) +{ + TestObject *tobject, *sigarg; + gchar *string = NULL; + + 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 (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS); + + tobject = g_object_new (TEST_TYPE_OBJECT, NULL); + sigarg = g_object_new (TEST_TYPE_OBJECT, NULL); + g_signal_emit_by_name (tobject, "test-signal", sigarg, NULL, &string); + g_message ("signal return: \"%s\"", string); + g_free (string); + + g_object_unref (sigarg); + g_object_unref (tobject); + + g_message ("%s done", argv[0]); + + return 0; +}