On 22/09/2015 00:52, Phil Clayton wrote:
I see what you mean. I was thinking only about an interactive/batch
session. For an executable, it's not clear that it makes sense to have
a finalizable value at the top-level. Already something odd is
happening: in the attached example toplevel_eg1.sml, the executable has
a finalizer depending on whether PolyML.fullGC was called when building.
I've merged the current Finalizer branch into master on github.
I've been testing Finalizable and found a few things.
1. A finalizer that raises an exception causes the cleaning thread to
terminate. Attached patch 0001 handles exceptions from finalizers and
reports them.
2. I have an FFI-related test suite for checking finalization that
produces an output log. Now that finalizers are called asynchronously,
the log entries are out of place and the order is not deterministic.
Even carefully ordering text output and always flushing does not
entirely solve the problem: writing to stdOut from different threads
seems to lead to some corruption. What I needed was a function to
synchronously run all finalizers (like on exit) in the main thread. I
have added a function doGCAndFinalize in the attached patch 0002. I'm
not convinced by this patch but it resolves this issue.
3. For 5.5.2, when finalizeBefore is used, it appears that not all
finalizers are run by repeatedly calling PolyML.fullGC. This occurs on
exit and, with patch 0002 applied, when doGCAndFinalize is called. See
attached example test1.sml.gz. It appears that this has been fixed in
the current development by commit
d9ca031dd99161c93ba03c42af396dafbf8c8482
so I mention that just for information. I have no immediate need for
finalizeBefore, so this should not hold me up.
Phil,
I've been thinking about this for a while and reluctantly I've come to
the conclusion that the only option is to remove Finalizable from the
basis library. The problem is with trying to give a clear definition of
what it does in the presence of all these variables.
At the heart of the difficulty is the view of what the garbage collector
does. The idea of the garbage collector is that it should not have an
observable effect on the program and so it can be run in various forms,
minor collections or major collections, at various times. It guarantees
not to remove data that may be required in the future.
Adding finalisers in this way turns this on its head. It makes the GC
observable and it requires, to some extent, that the collector should
guarantee to remove objects that are no longer required.
I really don't think this is achievable or even desirable. Trying to
achieve finalisation by using reachability makes the program
unpredictable and subject to changes in quite unexpected ways. The
effect of commit d9ca031dd99161c93ba03c42af396dafbf8c8482 is a specific
example. This commit changed the way some run-time system calls were
handled on the X86 so that registers were not preserved across RTS
calls. The reason for this was to try to speed up the calls. The fact
that it had an observable effect on the program is worrying to say the
least.
I've added "touch" to the Weak structure so you can implement the
original Finalizable structure yourself and that's probably easiest for you.
Best regards,
David
_______________________________________________
polyml mailing list
[email protected]
http://lists.inf.ed.ac.uk/mailman/listinfo/polyml