@@ -23,6 +23,7 @@ module Make (Data : Binable.S) = struct
2323 ; reusable_keys : int Queue .t
2424 (* * A list of ids that are no longer reachable from OCaml runtime, but
2525 haven't been cleared inside the LMDB disk cache *)
26+ ; queue_guard : Error_checking_mutex .t
2627 }
2728
2829 (* * How big can the queue [reusable_keys] be before we do a cleanup *)
@@ -32,16 +33,25 @@ module Make (Data : Binable.S) = struct
3233 Async.Deferred.Result. map (Disk_cache_utils. initialize_dir path ~logger )
3334 ~f: (fun path ->
3435 let env, db = Rw. create path in
35- { env; db; counter = ref 0 ; reusable_keys = Queue. create () } )
36+ { env
37+ ; db
38+ ; counter = ref 0
39+ ; reusable_keys = Queue. create ()
40+ ; queue_guard = Error_checking_mutex. create ()
41+ } )
3642
3743 type id = { idx : int }
3844
3945 let get ({ env; db; _ } : t ) ({ idx } : id ) : Data.t =
4046 Rw. get ~env db idx |> Option. value_exn
4147
42- let put ({ env; db; counter; reusable_keys } : t ) (x : Data.t ) : id =
48+ let put ({ env; db; counter; reusable_keys; queue_guard } : t ) (x : Data.t ) :
49+ id =
4350 let idx =
44- match Queue. dequeue reusable_keys with
51+ match
52+ Error_checking_mutex. critical_section queue_guard ~f: (fun () ->
53+ Queue. dequeue reusable_keys )
54+ with
4555 | None ->
4656 (* We don't have reusable keys, assign a new one nobody ever used *)
4757 incr counter ; ! counter - 1
@@ -57,10 +67,14 @@ module Make (Data : Binable.S) = struct
5767 critical section. LMDB critical section then will be re-entered if
5868 it's invoked directly in a GC hook.
5969 This causes mutex double-acquiring and node freezes. *)
60- Queue. enqueue reusable_keys idx ) ;
61- if Queue. length reusable_keys > = reuse_size_limit then (
62- Queue. iter reusable_keys ~f: (fun to_remove -> Rw. remove ~env db to_remove) ;
63- Queue. clear reusable_keys ) ;
70+ Error_checking_mutex. critical_section queue_guard ~f: (fun () ->
71+ Queue. enqueue reusable_keys idx ) ) ;
72+
73+ Error_checking_mutex. critical_section queue_guard ~f: (fun () ->
74+ if Queue. length reusable_keys > = reuse_size_limit then (
75+ Queue. iter reusable_keys ~f: (fun to_remove ->
76+ Rw. remove ~env db to_remove ) ;
77+ Queue. clear reusable_keys ) ) ;
6478 Rw. set ~env db idx x ;
6579 res
6680
0 commit comments