Skip to content

Commit 92daa44

Browse files
committed
Eliminate a level of indirection and reduce size via unsafe cast
1 parent 950f7ec commit 92daa44

File tree

1 file changed

+42
-27
lines changed

1 file changed

+42
-27
lines changed

src/kcas.ml

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,7 @@ let resume_awaiters result = function
6161

6262
type determined = [ `After | `Before ]
6363

64-
type 'a loc = { state : 'a state Atomic.t; id : int }
65-
66-
and 'a state = {
64+
type 'a state = {
6765
mutable before : 'a;
6866
mutable after : 'a;
6967
mutable casn : casn;
@@ -84,6 +82,21 @@ and cass =
8482
and casn = status Atomic.t
8583
and status = [ `Undetermined of cass | determined ]
8684

85+
(**)
86+
and 'a loc = { mutable _state : 'a state; id : int }
87+
88+
external as_atomic : 'a loc -> 'a state Atomic.t = "%identity"
89+
90+
let make_loc state id = { _state = state; id } [@@inline]
91+
(**)
92+
93+
(*
94+
and 'a loc = { state : 'a state Atomic.t; id : int }
95+
96+
let as_atomic loc = loc.state [@@inline]
97+
let make_loc state id = { state = Atomic.make state; id } [@@inline]
98+
*)
99+
87100
let is_cmp casn state = state.casn != casn [@@inline]
88101

89102
module Mode = struct
@@ -126,12 +139,13 @@ let rec verify casn = function
126139
| NIL -> `After
127140
| CASN { loc; state; lt; gt; _ } -> (
128141
if lt == NIL then
129-
if is_cmp casn state && fenceless_get loc.state != state then `Before
142+
if is_cmp casn state && fenceless_get (as_atomic loc) != state then
143+
`Before
130144
else verify casn gt
131145
else
132146
match verify casn lt with
133147
| `After ->
134-
if is_cmp casn state && fenceless_get loc.state != state then
148+
if is_cmp casn state && fenceless_get (as_atomic loc) != state then
135149
`Before
136150
else verify casn gt
137151
| `Before -> `Before)
@@ -152,7 +166,7 @@ let rec determine casn status = function
152166
let status = if lt != NIL then determine casn status lt else status in
153167
if status < 0 then status
154168
else
155-
let current = Atomic.get loc.state in
169+
let current = Atomic.get (as_atomic loc) in
156170
if state == current then
157171
determine casn (status lor (1 + Bool.to_int (is_cmp casn state))) gt
158172
else
@@ -181,7 +195,7 @@ let rec determine casn status = function
181195
(match current.awaiters with
182196
| [] -> ()
183197
| awaiters -> record.awaiters <- awaiters);
184-
if Atomic.compare_and_set loc.state current state then
198+
if Atomic.compare_and_set (as_atomic loc) current state then
185199
determine casn (status lor a_cas) gt
186200
else determine casn status eq
187201
| #determined -> raise Exit
@@ -272,13 +286,13 @@ module Retry = struct
272286
end
273287

274288
let add_awaiter loc before awaiter =
275-
let state_old = fenceless_get loc.state in
289+
let state_old = fenceless_get (as_atomic loc) in
276290
let state_new =
277291
let awaiters = awaiter :: state_old.awaiters in
278292
{ before; after = before; casn = casn_after; awaiters }
279293
in
280294
before == eval state_old
281-
&& Atomic.compare_and_set loc.state state_old state_new
295+
&& Atomic.compare_and_set (as_atomic loc) state_old state_new
282296

283297
let[@tail_mod_cons] rec remove_first x' removed = function
284298
| [] ->
@@ -287,13 +301,13 @@ let[@tail_mod_cons] rec remove_first x' removed = function
287301
| x :: xs -> if x == x' then xs else x :: remove_first x' removed xs
288302

289303
let rec remove_awaiter loc before awaiter =
290-
let state_old = fenceless_get loc.state in
304+
let state_old = fenceless_get (as_atomic loc) in
291305
if before == eval state_old then
292306
let removed = ref true in
293307
let awaiters = remove_first awaiter removed state_old.awaiters in
294308
if !removed then
295309
let state_new = { before; after = before; casn = casn_after; awaiters } in
296-
if not (Atomic.compare_and_set loc.state state_old state_new) then
310+
if not (Atomic.compare_and_set (as_atomic loc) state_old state_new) then
297311
remove_awaiter loc before awaiter
298312

299313
let block loc before =
@@ -305,13 +319,13 @@ let block loc before =
305319
raise cancellation_exn)
306320

307321
let rec update_no_alloc backoff loc state f =
308-
let state' = fenceless_get loc.state in
322+
let state' = fenceless_get (as_atomic loc) in
309323
let before = eval state' in
310324
match f before with
311325
| after ->
312326
state.after <- after;
313327
if before == after then before
314-
else if Atomic.compare_and_set loc.state state' state then (
328+
else if Atomic.compare_and_set (as_atomic loc) state' state then (
315329
state.before <- after;
316330
resume_awaiters before state'.awaiters)
317331
else update_no_alloc (Backoff.once backoff) loc state f
@@ -320,23 +334,24 @@ let rec update_no_alloc backoff loc state f =
320334
update_no_alloc backoff loc state f
321335

322336
let rec exchange_no_alloc backoff loc state =
323-
let state' = fenceless_get loc.state in
337+
let state' = fenceless_get (as_atomic loc) in
324338
let before = eval state' in
325-
if before == state.after || Atomic.compare_and_set loc.state state' state then
326-
resume_awaiters before state'.awaiters
339+
if
340+
before == state.after || Atomic.compare_and_set (as_atomic loc) state' state
341+
then resume_awaiters before state'.awaiters
327342
else exchange_no_alloc (Backoff.once backoff) loc state
328343

329344
let is_obstruction_free casn =
330345
fenceless_get casn == (Mode.obstruction_free :> status)
331346
[@@inline]
332347

333348
let cas loc before state =
334-
let state' = fenceless_get loc.state in
349+
let state' = fenceless_get (as_atomic loc) in
335350
let before' = state'.before and after' = state'.after in
336351
((before == before' && before == after')
337352
|| before == if is_after state'.casn then after' else before')
338353
&& (before == state.after
339-
|| Atomic.compare_and_set loc.state state' state
354+
|| Atomic.compare_and_set (as_atomic loc) state' state
340355
&& resume_awaiters true state'.awaiters)
341356
[@@inline]
342357

@@ -347,11 +362,11 @@ module Loc = struct
347362
type 'a t = 'a loc
348363

349364
let make after =
350-
let state = Atomic.make @@ new_state after and id = Id.get_unique () in
351-
{ state; id }
365+
let state = new_state after and id = Id.get_unique () in
366+
make_loc state id
352367

353368
let get_id loc = loc.id [@@inline]
354-
let get loc = eval (Atomic.get loc.state)
369+
let get loc = eval (Atomic.get (as_atomic loc))
355370

356371
let rec get_as f loc =
357372
let before = get loc in
@@ -366,14 +381,14 @@ module Loc = struct
366381
cas loc before state
367382

368383
let update ?(backoff = Backoff.default) loc f =
369-
let state' = fenceless_get loc.state in
384+
let state' = fenceless_get (as_atomic loc) in
370385
let before = eval state' in
371386
match f before with
372387
| after ->
373388
if before == after then before
374389
else
375390
let state = new_state after in
376-
if Atomic.compare_and_set loc.state state' state then
391+
if Atomic.compare_and_set (as_atomic loc) state' state then
377392
resume_awaiters before state'.awaiters
378393
else update_no_alloc (Backoff.once backoff) loc state f
379394
| exception Retry.Later ->
@@ -392,7 +407,7 @@ module Loc = struct
392407
let decr ?backoff loc = update ?backoff loc dec |> ignore
393408

394409
let has_awaiters loc =
395-
let state = Atomic.get loc.state in
410+
let state = Atomic.get (as_atomic loc) in
396411
state.awaiters != []
397412
end
398413

@@ -435,7 +450,7 @@ module Op = struct
435450
| [] -> determine_for_owner casn cass
436451
| CAS (loc, before, after) :: rest ->
437452
if before == after && is_obstruction_free casn then
438-
let state = fenceless_get loc.state in
453+
let state = fenceless_get (as_atomic loc) in
439454
before == eval state && run (insert cass loc state) rest
440455
else
441456
run
@@ -444,7 +459,7 @@ module Op = struct
444459
in
445460
let (CAS (loc, before, after)) = first in
446461
if before == after && is_obstruction_free casn then
447-
let state = fenceless_get loc.state in
462+
let state = fenceless_get (as_atomic loc) in
448463
before == eval state
449464
&& run (CASN { loc; state; lt = NIL; gt = NIL; awaiters = [] }) rest
450465
else
@@ -460,7 +475,7 @@ module Xt = struct
460475
}
461476

462477
let update0 loc f xt lt gt =
463-
let state = fenceless_get loc.state in
478+
let state = fenceless_get (as_atomic loc) in
464479
let before = eval state in
465480
let after = f before in
466481
let state =

0 commit comments

Comments
 (0)