[GUI] Re: Events and finalizers

Nick Name nick.name@inwind.it
Mon, 10 Mar 2003 21:36:00 +0100

On Mon, 10 Mar 2003 18:12:19 +0100
George Russell <ger@tzi.de> wrote:

>  Well there are two approaches:
>  (1) you provide a more complicated function which in addition to the
>  new      event, returns an IO () action which unbinds it.  This is
>  what HTk      does, in general, though for many simple examples it is
>  of course not      required.
>  (2) in many but not all cases it is possible to work out that the
>  stream      can be automatically deregistered.  For example, as well
>  as finalizers      you can also forget the stream when the object is
>  destroyed.

Exactly the same thing wich I am discussing with A.Reid in haskell-cafe;
but finalizers don't "finalize" immediately in some cases, even if they
might be satisfying. Moreover, there might be a different approach
involving a list of "unsafePerformIO" values to uninstall the callbacks
earlier, but I am not sure if it's worth the drawbacks.


I want to explain better what you just stated: "a callback
 model also has to have a way of deinstalling the callback".

If we return, together with the stream, the IO action used to unregister
the callback, it could easily become of no use if we pass the stream to
a new thread. We can't then know when that thread finishes to use the
stream (we could pass the closing action together with the stream,
anyway), so generally we HAVE to rely on garbage collection and
finalizers. But this is the same thing of registering a callback wich
multiplexes events to two threads, and the same issue.


As usual, if there are two different approaches, each one with
advantages and disadvantages, I prefer both, so the interface of a
generic Stream library should provide both

getStream :: IO [a]


getStreamAndTheOtherThing :: (IO [a],IO ())

The former should use finalizers to deallocate any resource when
appropriate, the latter could eventually use them anyway.

However, George, there are other problems with streams, wich are leading
me to a conclusion; before revealing it :) , here's some sample issue:

- sometimes, the stream is produced with a synchronized model: you ask
for a stream element only when you are ready to process it. This is used
in gtk2 to avoid a backlog of mouse motion messages. We have to find a
way (perhaps with a list of unsafeInterleaveIO results) to easily handle
such cases; or maybe you already got it ?

- if we want a library wich generically models a changing state, we have
to deal with three different types, and combination of those: State,
Input streams and Output streams. I provide now an example of any of
these categories, and of any combination of these (directly taken from
the comments I wrote last night on my source code :))  
   -- The standard input is only an Input, it has no notion of "current"
   -- value

   -- The standard output is only an Output

   -- The current time is only a State, it makes no sense to "listen" to
   -- it since it's a continuous value, but you can read it at a given
   -- moment

   -- An MVar has only State and Output 

   -- A Chan has only Input and Output

   -- The mouse position has Input and State

   -- A Port (in M.C. terminology) has Input,Output and State


I propose here to join our efforts and design a robust and generic
stream library, wich has to be thread-safe, and subsume MVars, Channels
and M.Chackravarty's Ports. I am doing such a work alone to use it in my
future projects, and it grows up well, but of course one thing is me, a
student, doing an hobbist work, and another thing is to work together.
We don't have to waste time, just to solve the main issues and produce a
clean and working implementation.

An example of things to decide includes wether to use constructor
classes or multiparameter type classes with functional dependencies
(once stated that "we are GHC dependent anyway", to quote Axel)

My experience (and your, I guess) is that such a library can be
implemented correctly in a couple of days, so there shouldn't be any
problem, after some week of planning. I propose this just to avoid each
stream-lover to rewrite everithing again each time. What do you think?

If so, the GUI task force will only have to be kind and use a generic
layer for state handling, say a "Var" type with "getVar" and "setVar",
so that we can provide an implementation wich also has streams when we
are done.

If anyone (not just George) is interested, the best thing to do is to
post on the haskell mailing list to ask for interested people, and then
do the job. What do you think?