David,

I think weak references could do the job. Better still, I may be able to adapt (shamelessly copy) MLtonFinalizable:
https://github.com/MLton/mlton/blob/master/basis-library/mlton/finalizable.sig
https://github.com/MLton/mlton/blob/master/basis-library/mlton/finalizable.sml
This would have the added bonus of a common interface for finalizable values between the compilers.

The main question is when to check the weak references. Is there some way to register a function to be called immediately after a GC? I'll investigate using a separate thread and the mutex which may be better anyway.

Finalizers should also be called when the ML session exits. It appears that functions registered with OS.Process.atExit are always run before Poly/ML exits (whether or not there is an explicit call to OS.Process.exit). Can you confirm that?

I was wondering how to implement the 'touch' function of MLTON_FINALIZABLE that forces a weak reference to stay alive. The expression
  ignore (PolyML.pointerEq (x, x) orelse raise Fail "touch"; print "");
seems to prevent Poly/ML optimizing the dependence on x away and works for any type x. Bizarrely, I found that without print "", the weak reference stayed alive. Can you think of something simpler?

Finally, a couple of general issues:

1. I was getting some unexpected behaviour with weak references using Poly/ML 5.5.0 - see the following example. Poly/ML 5.5.2 behaved as expected though. Does that mean 5.5.0 should be avoided?

  local
    val w = Weak.weak (SOME (ref ()))
  in
    fun check () = isSome (!w)
  end
  ;
  check ();
  val () = PolyML.fullGC ();
  check ();  (* false for 5.5.2, ok; true for 5.5.0 - issue? *)

2. The function weakArray confuses me although I doubt I will need to use it. It's not clear why it would be called with a reference, i.e. non-NONE argument because that is duplicated for every array element. Furthermore, if it is called with a non-NONE argument and the array size is more than 1, then this can crash Poly/ML. For example, entering the following in the top-level:

  val wa = Weak.weakArray (2, SOME (ref ()));
  PolyML.fullGC ();
  wa; (* seg fault *)

Regards,
Phil

15/09/15 13:21, David Matthews wrote:
On 14/09/2015 22:36, Phil Clayton wrote:
I am trying to create an SML binding to a C function that returns an
array that the caller must free.  Usually, there is a free function that
takes just the array (as a pointer) which can be attached as a finalizer
with CInterface.setFinal.  I have encountered a case [1] where the
caller must also pass the size of the array, returned when the array is
created, to the free function.

Phil,
I wonder if this is a case for the use of a weak reference (
http://www.polyml.org/documentation/Reference/Weak.html ) ?  Have a look
at this link and see whether it would work for you.

Essentially, what weak references do is allow you to run finalisers in
"ML space".  CInterface.setFinal sets up a C function to be run as a
finaliser and the GC runs these immediately when it detects an
unreferenced "vol".  It can't run an ML function at that point because
the ML heap is still being collected.  Changes to weak references are
notified at some point after ML is resumed after the GC.

If you've got any questions please ask.  I'd also be interested to know
if it solves your problem.

Regards,
David



_______________________________________________
polyml mailing list
polyml@inf.ed.ac.uk
http://lists.inf.ed.ac.uk/mailman/listinfo/polyml

Reply via email to