[MLton-devel] Re: [MLton-user] ffi pointer lifetime

Matthew Fluet fluet@cs.cornell.edu
Tue, 13 May 2003 19:45:11 -0400 (EDT)


> > It is all a bit weird since counting on finalization order is definitely a
> > bad idea any way.
>
> I agree with this.  I think this makes it a good idea to do what we do
> now with the reversal every time, or something equally bizarre, and
> require the user to build additional structure on top of finalization
> if they want a particular order.  And document that finalization order
> is unspecified.

I guess; I admit I haven't thought about it much.

Here's the best I could come up with for C-side malloc/free:

structure F = MLton.Finalize

local
  val nop = _ffi "nop": Word32.word ref -> unit;
in
  datatype cptr = CPtr of Word32.word ref
  fun getW (CPtr w) = w
  fun make (w: Word32.word, ptrs: cptr list, free: Word32.word -> unit) =
    let
      val ptr = CPtr (ref w)
    in
      F.finalize (ptr, fn () =>
		  (List.app (nop o getW) ptrs;
		   free w)) ;
      ptr
    end
end

local
  val listSing = _ffi "listSing": int -> Word32.word;
  val listCons = _ffi "listCons": int * Word32.word ref -> Word32.word;
  val listFree = _ffi "listFree": Word32.word -> unit;
  val listSum = _ffi "listSum": Word32.word ref -> int;
  fun install (w: Word32.word, ptrs: cptr list) : cptr =
    make (w, ptrs, listFree)
in
  val listSing : int -> cptr =
    fn i =>
    install (listSing i, [])
  val listCons : int * cptr -> cptr =
    fn (i,ptr) =>
    install (listCons (i, getW ptr), [ptr])
  val listSum : cptr -> int =
    fn ptr =>
    listSum (getW ptr)
end

Note that "uses" of C-ptrs (with the exception of listFree) are
Word32.word refs -- this ensures that the ref cell that is being tracked
by finalization is kept all the way until it is actually used.

One problem with the above is that finalization is "slow", in the sense
that because the ptrs list is kept in the closure of the finalization
function; therefore, we only free one cons-cell per GC.  I haven't been
able to come up with a better scheme.  The goal was to write:

fun f n = ... some function requiring limit checks ...
val l = listSing 2
val l = listCons (2,l)
val l = listCons (2,l)
val l = listCons (2,l)
val l = listCons (2,l)
val l = listCons (2,l)
val l = listCons (2,l)
val _ = MLton.GC.collect ()
val _ = f 100
val _ = print (concat ["listSum(l) = ",
		       Int.toString (listSum l),
		       "\n"])
val _ = MLton.GC.collect ()
val _ = f 100

and have listSum correctly compute 14, but then collect all the C-side
data after the second GC.collect().



-------------------------------------------------------
Enterprise Linux Forum Conference & Expo, June 4-6, 2003, Santa Clara
The only event dedicated to issues related to Linux enterprise solutions
www.enterpriselinuxforum.com

_______________________________________________
MLton-devel mailing list
MLton-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlton-devel