From 3b0ceb78213fa61bbf6a41b9a882157b0dc885ec Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 30 Nov 2018 10:28:47 -0600 Subject: [PATCH] fix(vector): free elements in more functions, add `fill_empty_slots_with` see #235 --- src/core/CCVector.ml | 41 ++++++++++++++++++++++++++++++++++++++++- src/core/CCVector.mli | 7 +++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/core/CCVector.ml b/src/core/CCVector.ml index a6e1aae0..1f1763b0 100644 --- a/src/core/CCVector.ml +++ b/src/core/CCVector.ml @@ -511,7 +511,6 @@ let map_in_place f v = *) -(* TODO: free elements *) let filter' p v = let i = ref 0 in (* cur element *) let j = ref 0 in (* cur insertion point *) @@ -525,6 +524,10 @@ let filter' p v = incr j ) else incr i done; + (* free elements *) + if !j > 0 && !j < v.size then ( + Array.fill v.vec !j (v.size - !j) v.vec.(0); + ); v.size <- !j (*$T @@ -682,6 +685,10 @@ let filter_map_in_place f v = incr i; incr j done; + (* free elements *) + if !j > 0 && !j < v.size then ( + Array.fill v.vec !j (v.size - !j) v.vec.(0); + ); v.size <- !j (*$QR @@ -691,6 +698,19 @@ let filter_map_in_place f v = to_list v = CCList.filter_map f l) *) +(* check it frees memory properly *) +(*$R + let s = "coucou" ^ "lol" in + let w = Weak.create 1 in + Weak.set w 0 (Some s); + let v = of_list ["a"; s] in + filter' (fun s -> String.length s <= 1) v; + assert_equal 1 (length v); + assert_equal "a" (get v 0); + Gc.major(); + assert_equal None (Weak.get w 0); +*) + let flat_map f v = let v' = create () in iter (fun x -> iter (push v') (f x)) v; @@ -817,6 +837,25 @@ let slice_seq v start len = let slice v = (v.vec, 0, v.size) +let fill_empty_slots_with v x : unit = + if capacity v > length v then ( + Array.fill v.vec (length v) (capacity v - length v) x; + ) + +(* check it frees memory properly *) +(*$R + let s = "coucou" ^ "lol" in + let w = Weak.create 1 in + Weak.set w 0 (Some s); + let v = of_list ["a"; s] in + ignore (pop_exn v :string); + assert_equal ~printer:string_of_int 1 (length v); + assert_equal ~printer:CCFun.id "a" (get v 0); + fill_empty_slots_with v ""; + Gc.major(); + assert_equal None (Weak.get w 0); +*) + let (--) i j = if i>j then init (i-j+1) (fun k -> i-k) diff --git a/src/core/CCVector.mli b/src/core/CCVector.mli index ddef0e64..72f66863 100644 --- a/src/core/CCVector.mli +++ b/src/core/CCVector.mli @@ -275,6 +275,13 @@ val slice_seq : ('a,_) t -> int -> int -> 'a sequence (** [slice_seq v start len] is the sequence of elements from [v.(start)] to [v.(start+len-1)]. *) +val fill_empty_slots_with : ('a, _) t -> 'a -> unit +(** [fill_empty_slots_with v x] puts [x] in the slots of [v]'s underlying + array that are not used (ie in the last [capacity v - length v] slots). + This is useful if you removed some elements from the vector and + want to be sure they can be GC'd by erasing them from the vector. + @since NEXT_RELEASE *) + val of_klist : ?init:('a, rw) t -> 'a klist -> ('a, rw) t val to_klist : ('a,_) t -> 'a klist val of_gen : ?init:('a, rw) t -> 'a gen -> ('a, rw) t