asynchronous exceptions

Stephen Weeks MLton@sourcelight.com
Thu, 27 Jul 2000 11:18:45 -0700 (PDT)


> > (2) good
> >   - handlers get to clean up when f() times out
> 
> I'm not sure why you wouldn't say that (1) also has this option. 

Because the thread that is evaluating f() gets thrown away.  So, if an 
outstream opened by f, it won't get closed.  

> Even if
> f() runs in a different thread, doesn't the 'a option get returned to the
> thread that calls timeLimit(t, f)? 

Yes.

> Of course, if the current thread is
> waiting for timeLimit to return, why does f() need to run in a separate
> thread at all? 

So the signal handler that is waiting for the alarm can do something
sensible -- i.e. drop the current running thread (f()) and return to
the original thread waiting for f().  I couldn't think of another way
to do it, without asynchronous exceptions.

I'm still heavily leaning towards (1).  Here's my current
implementation. 

      fun timeLimit(t: Time.t, f: unit -> 'a): 'a option =
	 let
	    val which = Itimer.Real
	    val signal = Itimer.whichSignal which
	    val res =
	       Thread.switch
	       (fn cur: 'a option Thread.t =>
		let
		   fun handler _ = Thread.prepend(cur, fn () => NONE)
		   val _ = Handler.set(signal, Handler.Handler handler)
		   val _ = Itimer.set{which = which,
				      value = t,
				      interval = Time.zero}
		   val t = Thread.new(fn () =>
				      let
					 val res =
					    let val x = f()
					    in fn () => SOME x
					    end handle e => fn () => raise e
				      in Thread.switch'(fn _ => (cur, res))
				      end)
		in (t, ())
		end)
	 in Handler.set(signal, Handler.Default)
	    ; res
	 end