[MLton-devel] Re: finalization in MLton
Stephen Weeks
MLton@mlton.org
Mon, 19 May 2003 14:53:36 -0700
> Stephen, your module seems to much more general than mine. Could you
> send me a sketch of the use-case example you had in mind when you made
> the interface? (It does not need to be on the list if we are getting
> OT).
The use case for finalizeBefore came from Matthew, and is for when one
wants to keep multiple pointers into a C data structure, e.g. a linked
list, and ensure that internal parts of the data structure aren't
freed to soon. For the code, see doc/examples/finalizable/.
As I see it, there are two differences between the MLton and MosML
modules:
* The MLton version allows multiple finalizers to be attached, at any
point in time, while the MosML version attaches a single finalizer
at creation time.
* The MLton version allows an order to be imposed on finalization.
The MosML version has no such facility.
The first difference is not a big deal, since each is implementable in
terms of the other, as the following code shows.
------------------------------------------------------------
signature MLTON_FINALIZABLE1 =
sig
type 'a t
val addFinalizer: 'a t * ('a -> unit) -> unit
val finalizeBefore: 'a t * 'b t -> unit
val new: 'a -> 'a t
val withValue: 'a t * ('a -> 'b) -> 'b
end
signature MLTON_FINALIZABLE2 =
sig
type 'a t
val finalizeBefore: 'a t * 'b t -> unit
val new: 'a * ('a -> unit) -> 'a t
val withValue: 'a t * ('a -> 'b) -> 'b
end
functor F12 (S: MLTON_FINALIZABLE1): MLTON_FINALIZABLE2 =
struct
open S
fun new (x, g) =
let
val f = S.new x
val _ = addFinalizer (f, g)
in
f
end
end
functor F21 (S: MLTON_FINALIZABLE2): MLTON_FINALIZABLE1 =
struct
datatype 'a t = T of {finalizable: 'a S.t,
finalizers: ('a -> unit) list ref}
fun new (x: 'a) =
let
val r: ('a -> unit) list ref = ref []
val f = S.new (x, fn x => List.app (fn f => f x) (!r))
in
T {finalizable = f,
finalizers = r}
end
fun addFinalizer (T {finalizers, ...}, f) =
finalizers := f :: !finalizers
fun finalizeBefore (T {finalizable = f, ...}, T {finalizable = f', ...}) =
S.finalizeBefore (f, f')
fun withValue (T {finalizable = f, ...}, g) =
S.withValue (f, g)
end
------------------------------------------------------------
I'm on the fence as to which of the two approaches should be exported
by MLton. Arguments either way appreciated.
As to finalizeBefore, again, it can be implemented on top of a more
primitive facility, as the following code shows.
------------------------------------------------------------
signature MLTON_FINALIZABLE0 =
sig
type 'a t
val new: 'a * ('a -> unit) -> 'a t
val withValue: 'a t * ('a -> 'b) -> 'b
end
functor F02 (S: MLTON_FINALIZABLE0): MLTON_FINALIZABLE2 =
struct
datatype 'a t = T of {afters: (unit -> unit) list ref,
finalizable: 'a S.t}
fun new (x, g) =
let
val afters = ref []
in
T {afters = afters,
finalizable = S.new (x, fn x =>
(g x; List.app (fn h => h ()) (!afters)))}
end
fun finalizeBefore (T {afters, ...}, T {finalizable = f, ...}) =
afters := (fn () => S.withValue (f, fn _ => ())) :: !afters
fun withValue (T {finalizable = f, ...}, g) =
S.withValue (f, g)
end
------------------------------------------------------------
In this case, the code seems tricky enough that it is worth including
finalizeBefore as part of MLton.Finalizable.
-------------------------------------------------------
This SF.net email is sponsored by: ObjectStore.
If flattening out C++ or Java code to make your application fit in a
relational database is painful, don't do it! Check out ObjectStore.
Now part of Progress Software. http://www.objectstore.net/sourceforge
_______________________________________________
MLton-devel mailing list
MLton-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlton-devel