17/09/15 16:12, David Matthews wrote:
On 17/09/2015 11:50, Phil Clayton wrote:
Thanks for the example - it was a useful to see how to use the Thread structure. And to see how easy it was. That's a nice library.
Attached is a first stab at implementing the FINALIZABLE signature shown below, which is identical to MLTON_FINALIZABLE. The code is based on the MLton implementation but with a number of differences. As mentioned in the other email, there seems to be an issue with finalizers not being run when exiting via OS.Process.exit.
Phil, I've begun by adding your code to a Finalizable branch in the github repository. The Finalizable structure and signature are included in the basis library when "poly" is built. It looks good and there's just a few points.
Great!
Your definition of "touch" should be fine. I think I now understand what's happening. At the moment at any rate the Poly/ML optimiser views the "store" as a single entity so it won't try to reorder or remove assignments just because they occur to locations that a more sophisticated analysis might show to be independent. By the way, I think perhaps the reason you had that rather bizarre behaviour with your previous definition of "touch" was that the address of the token was still in a register. Calling "print" before calling PolyML.fullGC will have replaced the address with something else.
I was wondering how finalisation should this interact with saving state? Should the state of the finalizers be restored when loadState is called? That is what will happen with the code as it currently is but it is possible to change that so that the state is not affected by loadState by using "non-overwritable" references.
That's an interesting question. If there is a case for using a finalizable value on resources whose state is entirely captured in the mutable and immutable store, then the finalizable state should probably be restored. Most uses I've seen are for C pointers which wouldn't be available in a new session but this is already a limitation of vols. At the moment I can't think of a reason to use non-overwritable refs.
I've altered the initialisation code slightly. It now uses PolyML.onEntry to start the thread and install the atExit handler. This ensures that these are run on every run. Have a look at basis/BasicStreamIO.sml which also contains a "non-overwritable" reference for the list of streams that must be closed when Poly/ML exits.
I spotted this too after building a test case as a stand-alone executable and nothing happened...
I wonder if the finalizers should be called outside updatePendingList i.e. after "mutex" has been released? The problem at the moment is that if a finalizer calls "new" it will deadlock. A finalizer should probably not be creating a new finalizer but equally we don't want deadlock.
Good point. That was easily fixed by making the function clean return a list of functions to run instead of a flag. See attached patch (created with git format-patch). (I can't do pull requests at the moment because Github no longer works properly with Firefox 16.)
Regards, Phil