package core_kernel

  1. Overview
  2. Docs
Industrial strength alternative to OCaml's standard library

Install

Dune Dependency

Authors

Maintainers

Sources

core_kernel-v0.15.0.tar.gz
sha256=34a0288f16027c6b90e4ad16cb5cc677d7063d310faf918748ce70f1745116c0

doc/src/core_kernel.weak_hashtbl/weak_hashtbl.ml.html

Source file weak_hashtbl.ml

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
74
75
76
77
78
79
80
81
82
83
84
85
86
open! Import


type ('a, 'b) t =
  { entry_by_key                             : ('a, 'b Weak_pointer.t) Hashtbl.t
  ; keys_with_unused_data                    : 'a Thread_safe_queue.t
  ; mutable thread_safe_run_when_unused_data : unit -> unit
  }
[@@deriving sexp_of]

module Using_hashable = struct
  let create ?growth_allowed ?size hashable =
    { entry_by_key                     = Hashtbl.Using_hashable.create ~hashable
                                           ?growth_allowed ?size ()
    ; keys_with_unused_data            = Thread_safe_queue.create ()
    ; thread_safe_run_when_unused_data = ignore
    }
  ;;
end

let create ?growth_allowed ?size m =
  Using_hashable.create ?growth_allowed ?size (Hashtbl.Hashable.of_key m)
;;

let set_run_when_unused_data t ~thread_safe_f =
  t.thread_safe_run_when_unused_data <- thread_safe_f;
;;

let remove t key = Hashtbl.remove t.entry_by_key key

(* In order for a call to [reclaim_space_for_keys_with_unused_data] to reclaim a key that
   was previously finalized, the weak pointer must have been cleared.  This relies on the
   fact that the OCaml garbage collector clears weaks and then runs finalizers. *)
let reclaim_space_for_keys_with_unused_data t =
  while Thread_safe_queue.length t.keys_with_unused_data > 0 do
    let key = Thread_safe_queue.dequeue_exn t.keys_with_unused_data in
    match Hashtbl.find t.entry_by_key key with
    | None -> ()
    | Some entry -> if Weak_pointer.is_none entry then remove t key
  done;
;;

let get_entry t key =
  Hashtbl.find_or_add t.entry_by_key key
    ~default:(fun () -> Weak_pointer.create ());
;;

let mem t key =
  match Hashtbl.find t.entry_by_key key with
  | None -> false
  | Some entry -> Weak_pointer.is_some entry
;;

let key_is_using_space t key = Hashtbl.mem t.entry_by_key key

let set_data t key entry data =
  Weak_pointer.set entry data;
  Gc.Expert.add_finalizer_last data (fun () ->
    Thread_safe_queue.enqueue t.keys_with_unused_data key;
    t.thread_safe_run_when_unused_data ());
;;

let replace t ~key ~data = set_data t key (get_entry t key) data

let add_exn t ~key ~data =
  let entry = get_entry t key in
  if Weak_pointer.is_some entry
  then failwiths ~here:[%here] "Weak_hashtbl.add_exn of key in use" t [%sexp_of: (_, _) t];
  set_data t key entry data;
;;

let find t key =
  match Hashtbl.find t.entry_by_key key with
  | None -> None
  | Some entry -> Weak_pointer.get entry
;;

let find_or_add t key ~default =
  let entry = get_entry t key in
  match Weak_pointer.get entry with
  | Some v -> v
  | None ->
    let data = default () in
    set_data t key entry data;
    data
;;
OCaml

Innovation. Community. Security.