Signal observations (was New 'GObject')



 
> > I have been wondering something about the gtk+ tool set.  I notice
> > that the concept of a virtual function and a signal are very closely
> > tied, but at the same time they appear seperately in a wealth of 
> > combinations.  Part of this is because the signal has a pointer to
> > the function that is virtual, but then it has flags for before, after
> > and other fun things.  
> > 
> > In effect this is the opposite of Qt.  In Qt the vfunc is provided
> > by the language and then calls the signal from the vfunc.  This allows
> > you the freedom to chose to call the signal or not, and to chose
> > the order of calling without all those flags.
> > 
> > Ie.  (C++ish psuedo code)
> 
> [...]
> 
> > Would it not have been simpler to have defined a signal and vfunc
> > seperately  and in a more flexible relationship?  Was this
> > intention to do the opposite of Qt or was this never thought about?
> 
> i don't actually think that peter's design goal for the signal system
> was to be different from Qt back then ;) (the signal system was actually
> designed pretty much exactly 3 years ago).

Okay, I don't know where the system came from.  I don't
know what other systems were in place at that time.
 
> > I am not proposing that this be done, it would be a huge
> > headache to change and not worth much at this point.  Still
> > I found the differences between the two striking. 
> 
> i don't think you actually learned to like the power and flexibility
> gtk's signal system provides, and are probably in doubt about it's
> real purposes.

I do see the power of the system at least from what I have ported
to C++.  Of course my priorities are different there.  It would
be absolutely impossible to have  
 
> 1) since in gtk you usually do *not* derive from a widget to slightly
>    customize its behaviour (simply because the overhead for that is
>    significantly higher in plain C as in real OO languages), a mechanism
>    was required to still be able to configure a widget's behaviour in
>    extensive ways. 

Clearly, we don't see any benefit from this at the C++ layer.  After
all a signal connection cost a lot more space and time than a 
C++ virtual function.  Thus we prefer overriding the virtual function
and deriving.  Things are very different on the C end and I realize that.
However, I think that it could be made just as workable the other.

(By the way this does trouble some C++ coders when translating.  
Since the first argument is the name of the object, but in C++
this is teh C++ object and not the C one we have to eat it.  Thus
user handle don't get the object that it came from.  So for us
it can't be anything more than a notification process.  We can't
add a new method to a defined class!)


> 2) also, as in any event-driven model with callback triggering, a flexible
>    system was required to invoke different kinds of callbacks for different
>    kinds of events with feedback on whether an event was handled or not (event
>    propagation is undoable without that).

I don't see that as different in either model.  Although the 
gtk+ rules of continuing events despite returning true because
there are more handlers on the signal is a problem with the
current system.  Again I campaign for marshallers being
able to stop emission based on the return code as the solution.  


> 3) finally, with widgets representing certain GUI components that may or may
>    not perform various actions and change state on their own behalf (well, on
>    behalf of the GUI user actually, but they kinda have their own will as
>    far as applications are concerned), a notification mechanism was
>    required to keep the application code updated on what's going on with the
>    widgets.


> now the short answer this, the Gtk+ signal system was designed to cover
> all three needs.
> 
> with signals being emitted for widgets that deliver events, and widgets being
> able to implement their own event handlers through vfuncs you can have any
> widget handle any event, override parent class' behaviour on event handling
> where desired and thus actually get the whole widget concept working in the
> first place (2).

This would be just as doable under the reverse situation...

  int Bar::set_somthing(int i)
    {
     int handled=something_changed(i);
     if (!handled) 
        { /*... */ }
   }

Clearly though the emission stop would be impossible under this scheme.

> then with user defined callbacks (signal handlers) that can be setup to get
> called *prior* to the widget's event handlers and optionally intercept them,
> you get the amount of flexible customization required as outlined in 1.
> creating a signal for a widget while leaving the vfunc NULL (or leave it out
> completely) and emitting it when certain state changes happened, finally gets
> you the functionality required in 3.

> since the latter type of signals serve mere notification nature and may get
> emitted from various places, they do not necessarily have an emit function
> exported through the widget's API and/or don't come with an actual handler
> implementation (this may be one of the cases you were referring to above,
> i don't know).

> of course gtk itself as well as application code don't make that hard
> of a distinction, you can connect to a signal that comes with an actuall
> member implementation, event though you just want to get notified, and
> sometimes we may even need to implement a member function for a signal
> that was initially designed to serve pure notification.

I do see a problem with multiple handlers.  There are some signals 
which you can only hook one thing because they return pointers  to
allocated objects or such.  But here adding a sigc style marshaller
that can do things like select or form a GList from the return codes
code handle.  However, it seems there should really be only one
handler for an object (not many as the list) and it should
be overidable from the current vfunc slot or a user slot.
Perhaps just making the API so that a signal has a handler which
runs first (either installed by user or default) and then either
stops the system or lets it progress would be a nice arrangement.
  
It seems like the two things "notification" and "handler" should
be separated at least by convention if nothing else.  I would really
like to have all the notifications named *_changed so that I know
that those are that the widget already changed something and is telling
me about it verses I haven't changed it yet something in it should
do it.  

> this may sound silly to someone to someone who's already familliar with
> gtk, but what i mean to point out here is:
> having one system implementing all three mechanisms provides you with
> great flexibility, but also blurs the distinction between the different
> conepts (which is not necessarily a bad thing).

Blurring does have some definite problems.  If you place notifications
and the handlers on the same signal, then what happens when the
signal aborts because the handler stopped emissions.  Your notification
may not get called.  Also this arrives at the need to block
that if you install a handler and it decided not to change value,
but other things are getting the notification that they are changed.

This really isn't so much in the signal system but how it is used.
Like using the syncing fields between the two.  The current
solution is to block by function (doesn't work in gtk-- because
we have methods).   Rather hooking the changed of one to the 
other would be more clear.  As the second one gets the call it
would not send a notification because nothing changed.  Separating
notification and handling would seem to correct these difficulties.

Thus there are several things blurred together... 
what is the real handler (there really should be only one) 
and who needs to be notified of a change.

Of course, I am not advocating any changes here, just providing some
food for thought. 

--Karl
  



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