Oh!  I hadn't thought of catch/clean-up/rethrow.  There is a 'finally' function that takes a clean-up action to be executed even if the main computation is killed:

    finally :: IO a -> IO b -> IO a

I think this is exactly what I need.  Thanks, Peter!

  - Conal

On Thu, Dec 18, 2008 at 3:15 PM, Peter Verswyvelen <bugfact@gmail.com> wrote:
I thought that killing a thread was basically done by throwing a ThreadKilled exception using throwTo. Can't these exception be caught? 

In C#/F# I usually use a similar technique: catch the exception that kills the thread, and perform cleanup. I have no experience with Haskell in that regard so most likely I'm missing something here...

2008/12/18 Conal Elliott <conal@conal.net>
I realized in the shower this morning that there's a serious flaw in my unamb implementation as described in http://conal.net/blog/posts/functional-concurrency-with-unambiguous-choice.  I'm looking for ideas for fixing the flaw.  Here's the code for racing computations:

    race :: IO a -> IO a -> IO a
    a `race` b = do v  <- newEmptyMVar
                    ta <- forkPut a v
                    tb <- forkPut b v
                    x  <- takeMVar  v
                    killThread ta
                    killThread tb
                    return x

    forkPut :: IO a -> MVar a -> IO ThreadId
    forkPut act v = forkIO ((act >>= putMVar v) `catch` uhandler `catch` bhandler)
     where
       uhandler (ErrorCall "Prelude.undefined") = return ()
       uhandler err                             = throw err
       bhandler BlockedOnDeadMVar               = return ()

The problem is that each of the threads ta and tb may have spawned other threads, directly or indirectly.  When I kill them, they don't get a chance to kill their sub-threads.

Perhaps I want some form of garbage collection of threads, perhaps akin to Henry Baker's paper "The Incremental Garbage Collection of Processes".  As with memory GC, dropping one consumer would sometimes result is cascading de-allocations.  That cascade is missing from my implementation.

Or maybe there's a simple and dependable manual solution, enhancing the method above.

Any ideas?

   - Conal



_______________________________________________
Reactive mailing list
Reactive@haskell.org
http://www.haskell.org/mailman/listinfo/reactive