1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
(*
Title: Weak references
Author: David Matthews
Copyright David Matthews 2008, 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*)
(* A weak reference or array contains option values. The SOME variant of
the option must contain a reference. This restriction is imposed because
they require pointer equality. A weak reference or array behaves just like
a normal ref or array with one difference. The garbage collector may set
a weak ref or the field of weak array to NONE if it currently contains
SOME r but r is not reachable other than through weak references. The
one proviso is that if r is contained in the executable it is always
reachable.
*)
signature WEAK =
sig
val weak: 'a ref option -> 'a ref option ref
val weakArray: int * 'a ref option -> 'a ref option array
val weakLock: Thread.Mutex.mutex
and weakSignal: Thread.ConditionVar.conditionVar
val touch : 'a ref -> unit
end;
structure Weak: WEAK =
struct
fun weak (v: 'a ref option): 'a ref option ref =
let
val System_alloc =
RunCall.run_call3 RuntimeCalls.POLY_SYS_alloc_store
in
System_alloc(0w1, 0wx60, v)
end
fun weakArray(n: int, v: 'a ref option): 'a ref option array =
let
(* An array consists of n+1 words with the first containing
the length. *)
val System_alloc =
RunCall.run_call3 RuntimeCalls.POLY_SYS_alloc_store
val System_setw = RunCall.run_call3 RuntimeCalls.POLY_SYS_assign_word;
val () = if n < 0 orelse n >= Array.maxLen then raise Size else ()
val arr = System_alloc(n+1, 0wx60, v)
in
System_setw(arr, 0, n);
arr
end
val weakLock = Thread.Mutex.mutex()
and weakSignal = Thread.ConditionVar.conditionVar()
(* touch is considered by the compiler as an access to the ref but doesn't
actually do anything with it. The idea is that it ensures that when a ref
is used as a token that this will access the ref and avoid the weak
reference becoming set to NONE. It's primarily there for long-term
security in the event that the compiler is sufficiently clever to
work out that something is no longer referenced. *)
fun touch v = RunCall.run_call1 RuntimeCalls.POLY_SYS_touch_final v
end;
|