wip: improved gc behavior for ccvector

This commit is contained in:
Simon Cruanes 2019-11-16 17:15:20 -06:00
parent 236a0c43ce
commit 1239960c42
2 changed files with 51 additions and 2 deletions

View file

@ -70,12 +70,23 @@ let init n f = {
let array_is_empty_ v = let array_is_empty_ v =
Array.length v.vec = 0 Array.length v.vec = 0
external as_float_arr : 'a array -> float array = "%identity"
external as_obj_arr : 'a array -> Obj.t array = "%identity"
let fill_with_junk_ (a:_ array) i len : unit =
if Obj.(tag (repr a) = double_array_tag) then (
Array.fill (as_float_arr a) i len 0.;
) else (
Array.fill (as_obj_arr a) i len (Obj.repr ());
)
(* assuming the underlying array isn't empty, resize it *) (* assuming the underlying array isn't empty, resize it *)
let resize_ v newcapacity = let resize_ v newcapacity =
assert (newcapacity >= v.size); assert (newcapacity >= v.size);
assert (not (array_is_empty_ v)); assert (not (array_is_empty_ v));
let new_vec = Array.make newcapacity v.vec.(0) in let new_vec = Array.make newcapacity v.vec.(0) in
Array.blit v.vec 0 new_vec 0 v.size; Array.blit v.vec 0 new_vec 0 v.size;
fill_with_junk_ new_vec v.size (newcapacity-v.size);
v.vec <- new_vec; v.vec <- new_vec;
() ()
@ -84,10 +95,35 @@ let resize_ v newcapacity =
ensure v 200; capacity v >= 200 ensure v 200; capacity v >= 200
*) *)
(*$T
let v = create() in push v 0.; push v 1.; push v 2.; 3=length v
let v = create() in push v 1.; push v 2.; push v 3.; 6. = (get v 0 +. get v 1 +. get v 2)
let v = create() in push v 0; push v 1; push v 2; 3=length v
let v = create() in push v 1; push v 2; push v 3; 6 = (get v 0 + get v 1 + get v 2)
let v = create() in push v "a"; push v "b"; push v "c"; 3=length v
let v = create() in push v "a"; push v "b"; push v "c"; "abc" = String.concat "" (to_list v)
*)
(*$R
let v = create() in
push v 0.; push v 1.;
clear v;
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
shrink v 2;
assert_equal 1. (fold (+.) 0. v);
clear v;
assert_equal 0 (size v);
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
assert_equal (1. +. 7. +. 10. +. 12.) (fold (+.) 0. v);
*)
(* grow the array, using [x] as a filler if required *) (* grow the array, using [x] as a filler if required *)
let grow_with_ v ~filler:x = let grow_with_ v ~filler:x =
if array_is_empty_ v then ( if array_is_empty_ v then (
v.vec <- Array.make 4 x let len = 4 in
v.vec <- Array.make len x;
(* do not really use [x], it was just for knowing the type *)
fill_with_junk_ v.vec 0 len;
) else ( ) else (
let n = Array.length v.vec in let n = Array.length v.vec in
let size = min (2 * n + 3) Sys.max_array_length in let size = min (2 * n + 3) Sys.max_array_length in
@ -135,6 +171,18 @@ let clear_and_reset v =
v.size <- 0; v.size <- 0;
v.vec <- [||] v.vec <- [||]
(* TODO*)
(*
let v = create() in
let a = Weak.create 1 in
push v ("hello"^"world");
Weak.set a 0 (Some (get v 0));
Gc.full_major(); Gc.compact();
OUnit.assert_bool "is alive" (Weak.check a 0);
Gc.full_major(); Gc.compact();
OUnit.assert_equal None (Weak.get a 0);
*)
let is_empty v = v.size = 0 let is_empty v = v.size = 0
let push_unsafe_ v x = let push_unsafe_ v x =

View file

@ -45,7 +45,8 @@ val return : 'a -> ('a, 'mut) t
@since 0.14 *) @since 0.14 *)
val make : int -> 'a -> ('a, 'mut) t val make : int -> 'a -> ('a, 'mut) t
(** [make n x] makes a vector of size [n], filled with [x]. *) (** [make n x] makes a vector of size [n], filled with [x].
The element [x] will possibly live as long as the vector. *)
val init : int -> (int -> 'a) -> ('a, 'mut) t val init : int -> (int -> 'a) -> ('a, 'mut) t
(** Init the vector with the given function and size. *) (** Init the vector with the given function and size. *)