awaitEval in Concurrent Haskell

Colin Runciman colin@cs.york.ac.uk
Thu, 06 Feb 2003 17:52:28 +0000


Simon,

>Next idea is to have a function
>	await :: a -> b -> b
>which is rather like 'seq' except that it waits for its first argument
>to be evaluated, whereas 'seq' evaluates it.  Then you could write a new
>version of 'length' which used await before every case expression. Is
>that what you had in mind?  A bit fragile, isn't it?
>
Something like await would  be enough I think.  It would not be 
necessary to write new
versions of all the functions to be data driven, just a single 
(overloaded) function
to convert a demanding function into a data-driven one. Something like this:

asEvaluated xs = await xs (case xs of
                                           (x:xs) -> asEvaluated x : 
asEvaluated xs
                                           []  -> [])

dataDriven f = f . asEvaluated

assert p xs = thread (... dataDriven p xs ...) xs

>How to implement 'await'.  We thought of three ways:
>
>1.  Implement a primitive checkEval :: a -> Bool, which tells whether
>something is evaluated; if not, it yields to other threads, as well as
>returning False.  So now you can have a busy-wait version of await thus:
>
>	await x y = case checkEval x of
>			True -> y
>                              False -> await x y
>
>2.  Implement await directly, by putting the thread in a pool of threads
>that the scheduler checks at regular intervals. They each just "watch" a
>thunk.  Still a busy-waiting solution.
>
>3.  Do the "right thing": implement 'await' by copying the thunk,
>replacing it by a "smart indirection" which also points to the
>non-suspended thread. When the indirection is evaluated, it just puts
>the suspended thread in the runnable pool before entering the thunk.
>Actually, this is probably no harder than (2).
>
I agree that 2 seems the most straightfoward, and not quite so busy as 1.
Unless I am misunderstanding 3 it could lead to problems if scheduling
can occur before evaluation of the thunk reaches a normal form.

>Now, it's true that it would take Simon or I less time to implement one
>of these than it would take your student to do, but we have so *many*
>things to implement, and each takes time.  And you will probably change
>your mind several times about what the right design should be (that's
>what research is like).  So there's a lot to be said for the wading in
>yourself.
>
The formula for implementation time is roughly
    initiationRites + inherentDifficulty / skillLevel
and I am pretty sure we could get by with just the await primitive.
So if there is any way you could find an early slot to do a
basic implementation of await, it would be much appreciated.

>What I can promise is that we'd turn around questions rapidly.
>
If we do end up trying to define await for ourselves, which source
files should we expect to modify and are there any likely pitfalls
in the subsequent rebuilding?

Thanks
Colin R