I'm trying to implement weak functional maps with ephemerons. Within the repl, things work fine. When I use the native or bytecode compilers, it looks like some things are not being collected.
Keys are boxed integers:
> type key = Key of int
Values are elements of an algebraic type with references to keys:
> type value =
> | Str of string
> | Link of key
Elements of the association list are key/value pairs wrapped in an ephemeron:
> module Eph = Ephemeron.K1
> type pair = (key,value) Eph.t
> let mk_pair key value =
> let eph = Eph.create () in
> Eph.set_key eph key;
> Eph.set_data eph value;
> eph
The following adds a new key/value pair to the assoc list:
> let intern idx value map =
> let key = Key idx in
> let eph = mk_pair key value in
> let map = eph::map in
> (key,map)
Next a function to update a key/value pair:
> let rec upd key new_value map =
> match map with
> | [] -> raise Not_found
> | pair::rest ->
> begin
> match Eph.get_key pair with
> | Some other_key when eq_key key other_key ->
> let eph = mk_pair key new_value in
> eph::rest
> | _ -> pair::(upd key new_value rest)
> end
Next, create a list of pairs:
> let str n = Str (String.make n '#');; (* Ensure value is boxed *)
> let (root,map) =
> let map = [] in
> let (k0,map) = intern 0 (str 1) map in
> let (k1,map) = intern 1 (Link k0) map in
> let (k2,map) = intern 2 (Link k1) map in
> (k2,map);;
Printing this yields:
> root=(Key 2), map=(Eph ((Key 2),(Link (Key 1))))
> (Eph ((Key 1),(Link (Key 0))))
> (Eph ((Key 0),(Str #)))
Next, update the root of the tree:
> let map = upd root (str 2) map;;
Which correctly binds (Key 2) to a string of length 2:
> root=(Key 2) map1=(Eph ((Key 2),(Str ##)))
> (Eph ((Key 1),(Link (Key 0))))
> (Eph ((Key 0),(Str #)))
Invoking gc from within the repl and printing again yields:
> root=(Key 2) map1=(Eph ((Key 2),(Str ##)))
> (Eph (None,None))
> (Eph (None,None))
which is exactly what one would expect. If however, I use the standalone bytecode compiler or the native compiler (4.07.1), then the entries are not nullified. Is this a bug or is there another way to persuade the garbage collector to clobber the entries?
Thanks
Lindsay