SMLofNJ.Cont.isolate

View: New views
8 Messages — Rating Filter:   Alert me  

SMLofNJ.Cont.isolate

by Dave Herman-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello--

In SML/NJ there's a useful function for invoking a thunk in an empty
continuation, called SMLofNJ.Cont.isolate. If I'm not mistaken, this
isn't too difficult to implement. Is this something that could be added
to MLton?

Thanks,
Dave

_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: SMLofNJ.Cont.isolate

by Matthew Fluet-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, 22 Apr 2008, Dave Herman wrote:
> In SML/NJ there's a useful function for invoking a thunk in an empty
> continuation, called SMLofNJ.Cont.isolate. If I'm not mistaken, this isn't
> too difficult to implement. Is this something that could be added to MLton?

I can't make sense of the isolate description
(http://www.smlnj.org/doc/SMLofNJ/pages/cont.html); the types don't seem
to work out:

  val isolate : ('a -> unit) -> 'a cont
  isolate f x
     Discard all live data from the calling context (except what is
     reachable from f or x), then call f(x), then exit. This may use much
     less memory then something like f(x) before exit().

I think what they really mean is that if
   val c = isolate f
then throw c x discards all live data ....

I'm sure it is possible to implement isolate simply in terms of callcc,
though it may not have the desired space behavior.

With the MLton.Thread structure (different from the Primitive.MLton.Thread
structure referenced in <src>/basis-library/mlton/cont.sml), you could get
the behavior of 'throw (isolate f) x' with the following:

fun isolateAndThrow (f: 'a -> unit) (x: 'a) : 'b =
   let
     val t = MLton.Thread.new f
     val r = MLton.Thread.prepare (t, x)
   in
     MLton.Thread.switch (fn _ => r)
   end

In the MLton.Cont structure, we have
   type 'a t = (unit -> 'a) -> unit

So it seems we could implement isolate as:

fun isolate (f: 'a -> unit) : 'a cont =
   fn x =>
   let
     val t = MLton.Thread.new (f o x)
     val r = MLton.Thread.prepare (t, ())
   in
     MLton.Thread.switch (fn _ => r)
   end

All untested.  And you need to call OS.Process.exit if the isolated
function returns normally (or exceptionally).  And I'm not 100% sure that
threads and continuations play nice together, but the above seems fairly
benign.


_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: SMLofNJ.Cont.isolate

by Dave Herman-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> I think what they really mean is that if
>   val c = isolate f
> then throw c x discards all live data ....

Yes, the documentation is bad, but I think this is what they mean.

> I'm sure it is possible to implement isolate simply in terms of callcc,
> though it may not have the desired space behavior.

Exactly.

> With the MLton.Thread structure (different from the
> Primitive.MLton.Thread structure referenced in
> <src>/basis-library/mlton/cont.sml), you could get the behavior of
> 'throw (isolate f) x' with the following:

Also known as `abort', which is all I really need. :)

> fun isolate (f: 'a -> unit) : 'a cont =
>   fn x =>
>   let
>     val t = MLton.Thread.new (f o x)
>     val r = MLton.Thread.prepare (t, ())
>   in
>     MLton.Thread.switch (fn _ => r)
>   end
>
> All untested.  And you need to call OS.Process.exit if the isolated
> function returns normally (or exceptionally).

Forgive my lack of familiarity with MLton threads... do you just mean this?

     let ...
     in
       MLton.Thread.switch (fn _ => r);
       OS.Process.exit ...
     end

(I'm still trying to understand the MLton.Thread library docs, sorry.)

> And I'm not 100% sure
> that threads and continuations play nice together, but the above seems
> fairly benign.

*gulp*

:)

thanks,
Dave

_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: SMLofNJ.Cont.isolate

by Dave Herman-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Dave Herman (foolishly?) wrote:

> Forgive my lack of familiarity with MLton threads... do you just mean this?
>
>     let ...
>     in
>       MLton.Thread.switch (fn _ => r);
>       OS.Process.exit ...
>     end

Maybe you meant this:

     fun isolate (f: 'a -> unit) : 'a cont =
       fn x =>
       let
         fun g () = (f x; OS.Process.exit OS.Process.success)
         val t = MLton.Thread.new g
         val r = MLton.Thread.prepare (t, ())
       in
         MLton.Thread.switch (fn _ => r)
       end

Yes?

Thanks again,
Dave

_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: SMLofNJ.Cont.isolate

by Matthew Fluet-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 25 Apr 2008, Dave Herman wrote:
>>  With the MLton.Thread structure (different from the Primitive.MLton.Thread
>>  structure referenced in <src>/basis-library/mlton/cont.sml), you could get
>>  the behavior of 'throw (isolate f) x' with the following:
>
> Also known as `abort', which is all I really need. :)

If you just need abort, then I would implement it directly in terms of the
MLton.Thread interface, rather than packaging it up as a continuation.
But, to match the SML/NJ interface, you would want to do it as a
continuation.

> Forgive my lack of familiarity with MLton threads... do you just mean this?
>
>     let ...
>     in
>       MLton.Thread.switch (fn _ => r);
>       OS.Process.exit ...
>     end

No.  MLton.Thread.switch is like abort, in that you completely abandon the
current context -- so that OS.Process.exit is never reached.  But,
similarly, because you've abandoned all contexts, if the switched-to
computation 'returns' there is no context to receive it.  So, we require
the switched-to thread to exit the program (or switch to another thread).

>>  And I'm not 100% sure that threads and continuations play nice together,
>>  but the above seems fairly benign.
>
> *gulp*

You should be fine, since you are using MLton.Thread as 'thread of
control' rather than as 'multiple threads of control'.  Where things would
appear to get tricky is if you capture the continuation in one spawned
thread and then throw to it in another spawned thread, then what "thread"
is the thrown computation?


_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: SMLofNJ.Cont.isolate

by Matthew Fluet-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 25 Apr 2008, Dave Herman wrote:

> Maybe you meant this:
>
>     fun isolate (f: 'a -> unit) : 'a cont =
>       fn x =>
>       let
>         fun g () = (f x; OS.Process.exit OS.Process.success)
>         val t = MLton.Thread.new g
>         val r = MLton.Thread.prepare (t, ())
>       in
>         MLton.Thread.switch (fn _ => r)
>       end
>
> Yes?

Pretty close.  You should handle both normal and exceptional returns from
the isolated computation, and to properly match the MLton.Cont interface,
the argument x is of type unit -> 'a, to be run in the thrown-to context
(though, in the isolate case, the thrown-to context is empty).  So,
something like:

   fun isolate (f: 'a -> unit) : 'a cont =
     fn (x : unit -> 'a) =>
     let
        fun g () = (f (x ()); OS.Process.exit OS.Process.success)
                   handle _ => OS.Process.exit OS.Process.failure
        val t = MLton.Thread.new g
        val r = MLton.Thread.prepare (t, ())
     in
       MLton.Thread.switch (fn _ => r)
     end

If you are interested in efficiency, you might consider specializing the
MLton.Thread.{new,preopare,switch} implementation for the isolate case.
(For example, you only ever have New threads, never Dead, Interrupted, or
Paused.)

_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: SMLofNJ.Cont.isolate

by Dave Herman-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> Pretty close.  You should handle both normal and exceptional returns
> from the isolated computation, and to properly match the MLton.Cont
> interface, the argument x is of type unit -> 'a, to be run in the
> thrown-to context (though, in the isolate case, the thrown-to context is
> empty).

Right right right. Thanks!

It all seems to be working for me. Now it's testing time...

Thanks for your help,
Dave

_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user

Re: SMLofNJ.Cont.isolate

by Matthew Fluet-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, 22 Apr 2008, Dave Herman wrote:
> In SML/NJ there's a useful function for invoking a thunk in an empty
> continuation, called SMLofNJ.Cont.isolate. If I'm not mistaken, this isn't
> too difficult to implement. Is this something that could be added to MLton?

I wrote up some notes on implementing isolate for MLton:
   http://mlton.org/MLtonContIsolateImplementation
It is available in SVN.


_______________________________________________
MLton-user mailing list
MLton-user@...
http://mlton.org/mailman/listinfo/mlton-user
LightInTheBox - Buy quality products at wholesale price