@@ -77,13 +77,13 @@ type ('k, 'v) t = ('k, 'v) state Atomic.t
7777
7878(* *)
7979
80- let lo_buckets = 1 lsl 3
80+ let lo_buckets = 1 lsl 4
8181
8282and hi_buckets =
8383 let mask = ceil_pow_2_minus_1 Sys. max_array_length in
8484 mask lxor (mask lsr 1 )
8585
86- let min_buckets_default = 1 lsl 4
86+ let min_buckets_default = Int. max lo_buckets ( 1 lsl 4 )
8787and max_buckets_default = Int. min hi_buckets (1 lsl 30 )
8888
8989let create (type k ) ?hashed_type ?min_buckets ?max_buckets () =
@@ -147,8 +147,8 @@ let copy _s i live_bs past_bs =
147147
148148let rec split hash lo live_bs high past_lo past_hi = function
149149 | Nil ->
150- set_if_fresh live_bs lo past_lo ;
151- set_if_fresh live_bs ( lo + high) past_hi
150+ set_if_fresh live_bs ( lo + high) past_hi ;
151+ set_if_fresh live_bs lo past_lo
152152 | Cons r ->
153153 if hash r.key land high = high then
154154 split hash lo live_bs high past_lo
@@ -173,7 +173,7 @@ let merge _s lo live_bs high past_bs =
173173 let ((Nil | Cons _) as past ) = merge past_lo past_hi in
174174 set_if_fresh live_bs lo past
175175
176- let resize s i =
176+ let resize s i_fresh =
177177 let past = s.past in
178178 if not (Past. is_size past) then
179179 let p = Past. unsafe_as_table past in
@@ -182,10 +182,23 @@ let resize s i =
182182 let past_bs = p.buckets in
183183 let past_n = Atomic_array. length past_bs in
184184 if live_n > past_n then
185- split s (i land (past_n - 1 )) s.buckets past_n p.buckets
185+ let lo = i_fresh land (past_n - lo_buckets) in
186+ let hi = lo + (lo_buckets - 1 ) in
187+ for i = lo to hi do
188+ split s i live_bs past_n past_bs
189+ done
186190 else if live_n < past_n then
187- merge s (i land (live_n - 1 )) s.buckets live_n p.buckets
188- else copy s i s.buckets p.buckets
191+ let lo = i_fresh land - lo_buckets in
192+ let hi = lo + (lo_buckets - 1 ) in
193+ for i = lo to hi do
194+ merge s i live_bs live_n past_bs
195+ done
196+ else
197+ let lo = i_fresh land - lo_buckets in
198+ let hi = lo + (lo_buckets - 1 ) in
199+ for i = lo to hi do
200+ copy s i live_bs past_bs
201+ done
189202
190203(* *)
191204
@@ -251,18 +264,26 @@ let mark_resize_finished s (p : _ Past.table) =
251264 while 0 < = ! i do
252265 begin match Atomic_array. unsafe_fenceless_get p.buckets ! i with
253266 | B (Frozen r ) -> size := length ! size r.spine
254- | _ -> failwith " mark_resize_finished"
267+ | B Fresh -> failwith " mark_resize_finished: Fresh"
268+ | B Nil -> failwith " mark_resize_finished: Nil"
269+ | B (Cons _ ) -> failwith " mark_resize_finished: Cons"
255270 end ;
256271 if (Sys. opaque_identity s).past != Past. of_table p then i := - 2 else decr i
257272 done ;
258273 if ! i = - 1 then s.past < - Past. of_size ! size
259274
260- let try_finish_resize (p : _ Past.table ) s mask =
261- let stride = Int64. to_int (Random. bits64 () ) lor 1 land mask in
262- let fuel = ref 16 in
275+ let try_finish_resize (p : _ Past.table ) s =
276+ let mask =
277+ Int. min (Atomic_array. length p.buckets) (Atomic_array. length s.buckets)
278+ - lo_buckets
279+ in
280+ let stride = Int64. to_int (Random. bits64 () ) lor lo_buckets land mask in
281+ let fuel = ref 8 in
263282 let i = ref stride in
264283 while ! fuel > 0 do
265- match Atomic_array. unsafe_fenceless_get s.buckets ! i with
284+ match
285+ Atomic_array. unsafe_fenceless_get s.buckets (! i + (lo_buckets - 1 ))
286+ with
266287 | B (Nil | Cons _ ) ->
267288 i := (! i + stride) land mask;
268289 if ! i = stride then fuel := - 1
@@ -301,7 +322,7 @@ let rec adjust_size t s mask delta result =
301322 end
302323 else begin
303324 let p = Past. unsafe_as_table past in
304- try_finish_resize p s mask
325+ try_finish_resize p s
305326 end
306327 end ;
307328 result
@@ -325,17 +346,29 @@ let rec adjust_size t s mask delta result =
325346 in
326347 result
327348 else
328- let p = Past. unsafe_as_table past in
349+ (* let p = Past.unsafe_as_table past in*)
329350 let _ : int =
330351 Atomic. fetch_and_add
331352 (Array. unsafe_get s.non_linearizable_size_delta 0 )
332353 delta
333354 in
334- try_finish_resize p s mask;
355+ (* try_finish_resize p s; *)
335356 result
336357
337358(* *)
338359
360+ let finish_resize s (p : _ Past.table ) =
361+ let n =
362+ Int. min (Atomic_array. length p.buckets) (Atomic_array. length s.buckets)
363+ in
364+ let i = ref (n - lo_buckets) in
365+ while 0 < = ! i do
366+ (* TODO: early exit *)
367+ resize s ! i;
368+ i := ! i - lo_buckets
369+ done ;
370+ mark_resize_finished s p
371+
339372let rec clear t =
340373 let s = Atomic. get t in
341374 let past = s.past in
@@ -352,20 +385,11 @@ let rec clear t =
352385 end
353386 else
354387 let p = Past. unsafe_as_table past in
355- let mask = Atomic_array. length s.buckets - 1 in
356- try_finish_resize p s mask;
388+ finish_resize s p;
357389 clear t
358390
359391(* *)
360392
361- let finish_resize s p =
362- let mask = Atomic_array. length s.buckets - 1 in
363- for i = 0 to mask do
364- (* TODO: early exit *)
365- resize s i
366- done ;
367- mark_resize_finished s p
368-
369393let rec to_seq t =
370394 let s = Atomic. get t in
371395 let past = s.past in
0 commit comments