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

Re: default signal closure via bindingset



[In all the messages in this thread, s/G_TYPE_NONE/G_TYPE_INVALID/g.]

Kevin Ryde wrote:
We're supposed to do all the
type registration when loading the module, before any code using the
things gets called.

It's not possible for a new fundamental type to exist without the
registration?

It's conceivable, but in that case gperl_value_to_sv will croak anyway. But still, avoiding the GHashTable assertion seems like a good idea to me.

That sounds like it could be a problem.  We use the presence of a
return value pointer to determine whether we're supposed to expect any
return values, but here they've passed ...  *brane asplode*

The g_signal_chain_from_overridden in GSignal.xs looks suspiciously like
it may do the same return_value typed as G_TYPE_NONE ...

        if (return_value) {
                /* Try to cover for people doing strange things */
                if (G_TYPE_NONE == G_VALUE_TYPE (return_value))
                        return_value = NULL;

A good way to get G_DISCARD.  That'd be for both
gperl_signal_class_closure_marshal() and gperl_closure_marshal() would
it?  There's no call for the two to differ is there?

I think I prefer Kevin's original approach (which is a copy of the approach taken in gperl_closure_marshal), because it avoids modifying an input parameter. But on the other hand it's nice to have G_VOID|G_DISCARD because then wantarray() and friends will give the correct answer inside the callback and we don't need to care about POPing the stack. gperl_callback_invoke does this.

So I committed the attached series of patches to trunk and the stable branch. Please scream if I screwed anything up.
Index: GType.xs
===================================================================
--- GType.xs	(revision 1077)
+++ GType.xs	(revision 1078)
@@ -273,10 +273,13 @@ registered with gperl_register_fundament
 GPerlValueWrapperClass *
 gperl_fundamental_wrapper_class_from_type (GType gtype)
 {
-	GPerlValueWrapperClass * res;
+	GPerlValueWrapperClass * res = NULL;
 	G_LOCK (wrapper_class_by_type);
-	res = (GPerlValueWrapperClass *)
-		g_hash_table_lookup (wrapper_class_by_type, (gpointer) gtype);
+	if (wrapper_class_by_type) {
+		res = (GPerlValueWrapperClass *)
+			g_hash_table_lookup (wrapper_class_by_type,
+			                     (gpointer) gtype);
+	}
 	G_UNLOCK (wrapper_class_by_type);
 	return res;
 }
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1077)
+++ ChangeLog	(revision 1078)
@@ -1,5 +1,10 @@
 2009-02-05  Torsten Schoenfeld  <kaffeetisch gmx de>
 
+	* GType.xs (gperl_register_fundamental_full): Handle
+	wrapper_class_by_type being NULL gracefully.  Patch by Kevin Ryde.
+
+2009-02-05  Torsten Schoenfeld  <kaffeetisch gmx de>
+
 	* Glib.xs: In Glib::filename_from_uri and filename_to_uri, use the
 	gchar converters for the hostname.  Patch by Kevin Ryde.
 
Index: MANIFEST
===================================================================
--- MANIFEST	(revision 1078)
+++ MANIFEST	(revision 1079)
@@ -62,6 +62,7 @@ t/lazy_loader.t
 t/make_helper.t
 t/options.t
 t/signal_emission_hooks.t
+t/signal_marshal.t
 t/signal_query.t
 t/tied_definedness.t
 TODO
Index: GType.xs
===================================================================
--- GType.xs	(revision 1078)
+++ GType.xs	(revision 1079)
@@ -983,6 +983,7 @@ gperl_signal_class_closure_marshal (GClo
 	/* does the function exist? then call it. */
 	if (slot && GvCV (*slot)) {
 		SV * save_errsv;
+		gboolean want_return_value;
 		int flags;
 		dSP;
 
@@ -1007,13 +1008,14 @@ gperl_signal_class_closure_marshal (GClo
 		/* note: keep this as closely sync'ed as possible with the
 		 * definition of GPERL_CLOSURE_MARSHAL_CALL. */
 		save_errsv = sv_2mortal (newSVsv (ERRSV));
-		flags = G_EVAL | (return_value ? G_SCALAR : G_VOID|G_DISCARD);
+		want_return_value = return_value && G_VALUE_TYPE (return_value);
+		flags = G_EVAL | (want_return_value ? G_SCALAR : G_VOID|G_DISCARD);
 		call_method (SvPV_nolen (method_name), flags);
 		SPAGAIN;
 		if (SvTRUE (ERRSV)) {
 			gperl_run_exception_handlers ();
 
-		} else if (return_value) {
+		} else if (want_return_value) {
 			gperl_value_from_sv (return_value, POPs);
 			PUTBACK;
 		}
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1078)
+++ ChangeLog	(revision 1079)
@@ -1,5 +1,12 @@
 2009-02-05  Torsten Schoenfeld  <kaffeetisch gmx de>
 
+	* MANIFEST
+	* GType.xs (gperl_signal_class_closure_marshal)
+	* t/signal_marshal.t: Correctly handle signals with no return type
+	when invoking signal class closures.  Patch by Kevin Ryde.
+
+2009-02-05  Torsten Schoenfeld  <kaffeetisch gmx de>
+
 	* GType.xs (gperl_register_fundamental_full): Handle
 	wrapper_class_by_type being NULL gracefully.  Patch by Kevin Ryde.
 
Index: t/signal_marshal.t
===================================================================
--- t/signal_marshal.t	(revision 0)
+++ t/signal_marshal.t	(revision 1079)
@@ -0,0 +1,54 @@
+#!perl
+package MyClass;
+use strict;
+use warnings;
+use Glib;
+
+use Glib::Object::Subclass
+  'Glib::Object',
+  signals => { mysig => { param_types => [],
+                          return_type => undef },
+             };
+
+sub INIT_INSTANCE {
+  my ($self) = @_;
+}
+
+sub do_mysig {
+  return 123;
+}
+
+
+package MySubClass;
+use strict;
+use warnings;
+use Glib;
+
+use Glib::Object::Subclass
+  'MyClass',
+  signals => { mysig => \&_do_mysubclass_mysig };
+
+sub INIT_INSTANCE {
+  my ($self) = @_;
+}
+
+our $MYSIG_RUNS = 0;
+
+sub _do_mysubclass_mysig {
+  my ($self) = @_;
+  $self->signal_chain_from_overridden;
+  $MYSIG_RUNS++;
+}
+
+
+package main;
+use strict;
+use warnings;
+use Glib;
+use Test::More tests => 1;
+
+my $obj = MySubClass->new;
+$obj->signal_emit ('mysig');
+
+is($MySubClass::MYSIG_RUNS, 1,
+   'marshaling a signal with no return type');
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1079)
+++ ChangeLog	(revision 1080)
@@ -1,5 +1,13 @@
 2009-02-05  Torsten Schoenfeld  <kaffeetisch gmx de>
 
+	* GClosure.xs (gperl_closure_marshal): Synchronize the way signals
+	with no return value are handled with how it's done in
+	gperl_signal_class_closure_marshal.  This means that Perl handlers
+	for these kinds of signals are now always called in void context,
+	as they should be.
+
+2009-02-05  Torsten Schoenfeld  <kaffeetisch gmx de>
+
 	* MANIFEST
 	* GType.xs (gperl_signal_class_closure_marshal)
 	* t/signal_marshal.t: Correctly handle signals with no return type
Index: GClosure.xs
===================================================================
--- GClosure.xs	(revision 1079)
+++ GClosure.xs	(revision 1080)
@@ -69,6 +69,7 @@ gperl_closure_marshal (GClosure * closur
 		       gpointer invocation_hint,
 		       gpointer marshal_data)
 {
+	gboolean want_return_value;
 	int flags;
 	guint i;
 	dGPERL_CLOSURE_MARSHAL_ARGS;
@@ -99,18 +100,15 @@ gperl_closure_marshal (GClosure * closur
 
 	PUTBACK;
 
-	flags = return_value ? G_SCALAR : G_DISCARD;
+	want_return_value = return_value && G_VALUE_TYPE (return_value);
+	flags = want_return_value ? G_SCALAR : G_VOID|G_DISCARD;
 
 	SPAGAIN;
 
 	GPERL_CLOSURE_MARSHAL_CALL (flags);
 
-	if (return_value) {
-		/* we need to remove the value to from the stack,
-		 * regardless of whether we do anything with it. */
-		SV * sv = POPs;
-		if (G_VALUE_TYPE (return_value))
-			gperl_value_from_sv (return_value, sv);
+	if (want_return_value) {
+		gperl_value_from_sv (return_value, POPs);
 		PUTBACK; /* vitally important */
 	}
 


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