Re: Finalizers strike back

2002-10-12 Thread Alastair Reid


 (It would be nice to have some concurrency in nhc98, of course, but
 I don't foresee that happening soon.)

I remember implementing cooperative concurrency in Hugs as being
rather easy.  Of course, that was building on a base which already used
a continuation passing IO monad...

If you want to try, I could dig out some details but the main issues
are:

1) When you have a choice of which thread to wake next, it matters
   which you wake next.  IIRC, waking the wrong one makes it impossible
   to implement a producer-consumer pattern.

2) There's a lot of interaction with non-deterministic exception
   handling.

3) unsafePerformIO foo had better not block since we have no way to
   block the non-monadic code that invoked it.  In that case, we 
   raise an exception or give up (don't remember which).


 Actually, I'm just wondering whether I can use the GC as a
 poor-man's scheduler.  If a finaliser blocks on an MVar, save its
 state, keep the finaliser in the pending queue, and return to the
 main thread.  Then on the next GC, try the same finaliser again, ad
 infinitum until it succeeds.

The finalizer won't become runnable until someone does a putMVar so
you can deal with this case by storing the finalizer's state in a
queue of blocked threads attached to the MVar and having putMVar do a
context switch to the thread at the head of the MVar's queue of
blocked threads.  If you want finalizers to have priority over other
threads, have two queues: one for finalizers, one for normal threads.


--
Alastair

___
FFI mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/ffi



Re: Finalizers strike back

2002-10-11 Thread Malcolm Wallace

George Russell [EMAIL PROTECTED] writes:

 it would normally be a good idea for implementations and programmers to
 provide and use MVars, even if they do not provide and use concurrency,
 ...   If NHC does not provide MVars, I think it should.

I don't think MVars make any sense without concurrency, so I don't see
the point of implementing the one without the other.  I'm willing to
be persuaded otherwise.  (It would be nice to have some concurrency
in nhc98, of course, but I don't foresee that happening soon.)

 I apologise to Malcolm, but in any case I doubt if implementing
 MVars in a world with only one thread would cost him a great deal of
 effort.

Well it would be simple enough provided you didn't mind your
computation halting with deadlock rather unpredictably.  :-)

Actually, I'm just wondering whether I can use the GC as a poor-man's
scheduler.  If a finaliser blocks on an MVar, save its state, keep
the finaliser in the pending queue, and return to the main thread.
Then on the next GC, try the same finaliser again, ad infinitum until
it succeeds.

Regards,
Malcolm
___
FFI mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/ffi



Re: Finalizers strike back

2002-10-11 Thread Fergus Henderson

On 11-Oct-2002, George Russell [EMAIL PROTECTED] wrote:
 I think we should remember that the FFI standard has to address various
 audiences
 (1) those who want to implement portable code in just FFI + Haskell98.
 This group does not have access to functions for conveniently manipulating
 mutable state, therefore Alastair's problem with IORefs will not be a problem
 for them. However Haskell inside finalizers will at any rate not harm them

This argument is invalid, because those who want to implement portable
code in just Haskel98 + FFI will very quickly use the FFI to implement
IORefs or something similar.

 Consider someone who, say, calls out from Haskell to Java (to do funny
 graphics, say) and writes a finalizer which calls Java code.  At the same time, they
 also want to do some completely separate pure computation in Haskell, which is made
 available to Java.  Since Java at least does have preemptive concurrency, while
 it is running at all, it is perfectly possible that Java will call the Haskell 
computation
 while the Java finalizer is running.  You want a license to make the roof fall in at 
this
 point; I don't think you should have it.

If you have a non-thread-safe Haskell implementation, and you try to
call it from two different threads without protecting this somehow,
then the roof *will* fall in at least some of the time.  This follows
directly from the definition of non-thread-safe.

So you want to disallow non-thread-safe Haskell implementations from
supporting the FFI?

-- 
Fergus Henderson [EMAIL PROTECTED]  |  I have always known that the pursuit
The University of Melbourne |  of excellence is a lethal habit
WWW: http://www.cs.mu.oz.au/~fjh  | -- the last words of T. S. Garp.
___
FFI mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/ffi



Re: Finalizers strike back

2002-10-11 Thread George Russell
Alastair Reid wrote:
 
  [snip] I'm not sure I really understand the problem.  The FFI
  standard (Release Candidate 4, the one I have printed out here) does
  not define IORefs, and of course Haskell 98 doesn't either.
  Therefore, although this code is broken, this particular example
  doesn't matter if all we are considering is code written in Haskell
  98 + FFI.
 
 If there's no shared mutable Haskell state, writing finalizers in
 Haskell buys you little - what does a finalizer do other than cleanup
 shared state?  (Note that it doesn't cleanup unshared state - what
 would be the point?)
[snip]
 What I hear you saying is that the FFI standard should depend on a
 concurrency standard.  I think there was a strong sentiment that we
 should avoid this.  I agree though that it is necessary if we allow
 Haskell finalizers.
[snip]
I think we should remember that the FFI standard has to address various
audiences
(1) those who want to implement portable code in just FFI + Haskell98.
This group does not have access to functions for conveniently manipulating
mutable state, therefore Alastair's problem with IORefs will not be a problem
for them.  However Haskell inside finalizers will at any rate not harm them.  
Furthermore
it is incorrect to say that just because there is no Haskell mutable state, there
is no reason such people may want it to be possible to call Haskell while a finalizer
is running.  Consider someone who, say, calls out from Haskell to Java (to do funny
graphics, say) and writes a finalizer which calls Java code.  At the same time, they
also want to do some completely separate pure computation in Haskell, which is made
available to Java.  Since Java at least does have preemptive concurrency, while
it is running at all, it is perfectly possible that Java will call the Haskell 
computation
while the Java finalizer is running.  You want a license to make the roof fall in at 
this
point; I don't think you should have it.
(2) those who want to implement portable code in FFI + Haskell98 + something else.
(I suspect this is the larger group.)  To discuss this at all we simply have to
speculate about what something else might be.  One obvious something else is 
mutable state.  Alastair is assuming that something else is IORefs but not MVars.
However I assert this is implausible or at least unfortunate, because for reasons I've
explained, it would normally be a good idea for implementations and programmers to 
provide
and use MVars, even if they do not provide and use concurrency, since otherwise you
can't write functions like Alastair's newObject and killObject without making 
unnecessary
assumptions about the properties of the implementation.  If NHC does not provide MVars,
I think it should.  I apologise to Malcolm, but in any case I doubt if implementing 
MVars
in a world with only one thread would cost him a great deal of effort.

To sum up, it's NOT that I want the FFI standard to depend on concurrency.  It's once 
again
that I don't want the FFI standard to depend on the absence of concurrency (as 
Alastair's
IORef code does).
___
FFI mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/ffi



Re: Finalizers strike back

2002-10-10 Thread Alastair Reid


 [snip] I'm not sure I really understand the problem.  The FFI
 standard (Release Candidate 4, the one I have printed out here) does
 not define IORefs, and of course Haskell 98 doesn't either.
 Therefore, although this code is broken, this particular example
 doesn't matter if all we are considering is code written in Haskell
 98 + FFI.

If there's no shared mutable Haskell state, writing finalizers in
Haskell buys you little - what does a finalizer do other than cleanup
shared state?  (Note that it doesn't cleanup unshared state - what
would be the point?)

I think IORefs are the most widely accepted extension of Haskell.  The
FFI spec doesn't depend on IORefs but it should certainly be designed
to work in an environment where they exist.

 However to me this code just looks totally wrong because of course I
 use GHC, a system with preemptive scheduling, and would regard it as
 incompetent to use anything other than an MVar here. 

I completely agree.

I do not believe we can have any useful form of Haskell finalizers
(meaning finalizers that manipulate shared Haskell state) without
adding MVars.

But, since concurrency is not so widely implemented as IORefs, we are
trying to produce an FFI design which does not require concurrency
extensions.

My solution to this conflict is not to add Haskell finalizers.

 However to me this code just looks totally wrong because of course I
 use GHC, a system with preemptive scheduling, and would regard it as
 incompetent to use anything other than an MVar here.  Even for Hugs
 I don't like this code, because [...]

I think you're taking my code out of context.  The purpose in writing
that code using IORefs was to show the kind of code you should not
write because it would suffer from race conditions.

I completely agree that some form of locking is required to make the
code safe. 

I guess I'd be willing to have Haskell finalizers if we agreed on an
appropriate form of locking that all implementers can and will
implement.

NHC currently lacks a locking mechanism.

I believe that using Hugs' MVars in conjunction with SimonM's patch
will lead to deadlock in the cases that would have suffered race
conditions using IORefs.

 Supposing we posit that there is a GlobalVariables standard.

Just want to remark that the variables don't have to be global.
Haskell finalizers are specified by closures and closures can point to
any IORefs you fancy.

 Anyone writing a finalizer should be aware (indeed the FFI standard
 should say) that the finalizer may be run at any point (after all,
 when else would you expect it to run) and should take precautions
 against it.  

What I hear you saying is that the FFI standard should depend on a
concurrency standard.  I think there was a strong sentiment that we
should avoid this.  I agree though that it is necessary if we allow
Haskell finalizers.


--
Alastair Reid [EMAIL PROTECTED]  
Reid Consulting (UK) Limited  http://www.reid-consulting-uk.ltd.uk/alastair/
___
FFI mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/ffi