Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / src / MLtonFinalizable.adoc
1 MLtonFinalizable
2 ================
3
4 [source,sml]
5 ----
6 signature MLTON_FINALIZABLE =
7 sig
8 type 'a t
9
10 val addFinalizer: 'a t * ('a -> unit) -> unit
11 val finalizeBefore: 'a t * 'b t -> unit
12 val new: 'a -> 'a t
13 val touch: 'a t -> unit
14 val withValue: 'a t * ('a -> 'b) -> 'b
15 end
16 ----
17
18 A _finalizable_ value is a container to which finalizers can be
19 attached. A container holds a value, which is reachable as long as
20 the container itself is reachable. A _finalizer_ is a function that
21 runs at some point after garbage collection determines that the
22 container to which it is attached has become
23 <:Reachability:unreachable>. A finalizer is treated like a signal
24 handler, in that it runs asynchronously in a separate thread, with
25 signals blocked, and will not interrupt a critical section (see
26 <:MLtonThread:>).
27
28 * `addFinalizer (v, f)`
29 +
30 adds `f` as a finalizer to `v`. This means that sometime after the
31 last call to `withValue` on `v` completes and `v` becomes unreachable,
32 `f` will be called with the value of `v`.
33
34 * `finalizeBefore (v1, v2)`
35 +
36 ensures that `v1` will be finalized before `v2`. A cycle of values
37 `v` = `v1`, ..., `vn` = `v` with `finalizeBefore (vi, vi+1)` will
38 result in none of the `vi` being finalized.
39
40 * `new x`
41 +
42 creates a new finalizable value, `v`, with value `x`. The finalizers
43 of `v` will run sometime after the last call to `withValue` on `v`
44 when the garbage collector determines that `v` is unreachable.
45
46 * `touch v`
47 +
48 ensures that `v`'s finalizers will not run before the call to `touch`.
49
50 * `withValue (v, f)`
51 +
52 returns the result of applying `f` to the value of `v` and ensures
53 that `v`'s finalizers will not run before `f` completes. The call to
54 `f` is a nontail call.
55
56
57 == Example ==
58
59 Suppose that `finalizable.sml` contains the following:
60 [source,sml]
61 ----
62 sys::[./bin/InclGitFile.py mlton master doc/examples/finalizable/finalizable.sml]
63 ----
64
65 Suppose that `cons.c` contains the following.
66 [source,c]
67 ----
68 sys::[./bin/InclGitFile.py mlton master doc/examples/finalizable/cons.c]
69 ----
70
71 We can compile these to create an executable with
72 ----
73 % mlton -default-ann 'allowFFI true' finalizable.sml cons.c
74 ----
75
76 Running this executable will create output like the following.
77 ----
78 % finalizable
79 0x08072890 = listSing (2)
80 0x080728a0 = listCons (2)
81 0x080728b0 = listCons (2)
82 0x080728c0 = listCons (2)
83 0x080728d0 = listCons (2)
84 0x080728e0 = listCons (2)
85 0x080728f0 = listCons (2)
86 listSum
87 listSum(l) = 14
88 listFree (0x080728f0)
89 listFree (0x080728e0)
90 listFree (0x080728d0)
91 listFree (0x080728c0)
92 listFree (0x080728b0)
93 listFree (0x080728a0)
94 listFree (0x08072890)
95 ----
96
97
98 == Synchronous Finalizers ==
99
100 Finalizers in MLton are asynchronous. That is, they run at an
101 unspecified time, interrupting the user program. It is also possible,
102 and sometimes useful, to have synchronous finalizers, where the user
103 program explicitly decides when to run enabled finalizers. We have
104 considered this in MLton, and it seems possible, but there are some
105 unresolved design issues. See the thread at
106
107 * http://www.mlton.org/pipermail/mlton/2004-September/016570.html
108
109 == Also see ==
110
111 * <!Cite(Boehm03)>