Skip to content

Commit 633bd32

Browse files
committed
Eliminate a level of indirection and reduce size via unsafe cast
1 parent 7c16ab4 commit 633bd32

File tree

1 file changed

+29
-25
lines changed

1 file changed

+29
-25
lines changed

src/kcas.ml

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ let resume_awaiters result = function
5656

5757
type determined = [ `After | `Before ]
5858

59-
type 'a loc = { state : 'a state Atomic.t; id : int }
59+
type 'a loc = { mutable _state : 'a state; id : int }
6060

6161
and 'a state = {
6262
mutable before : 'a;
@@ -79,6 +79,8 @@ and cass =
7979
and casn = status Atomic.t
8080
and status = [ `Undetermined of cass | determined ]
8181

82+
external as_atomic : 'a loc -> 'a state Atomic.t = "%identity"
83+
8284
let is_cmp casn state = state.casn != casn [@@inline]
8385

8486
module Mode = struct
@@ -121,12 +123,13 @@ let rec verify casn = function
121123
| NIL -> `After
122124
| CASN { loc; state; lt; gt; _ } -> (
123125
if lt == NIL then
124-
if is_cmp casn state && fenceless_get loc.state != state then `Before
126+
if is_cmp casn state && fenceless_get (as_atomic loc) != state then
127+
`Before
125128
else verify casn gt
126129
else
127130
match verify casn lt with
128131
| `After ->
129-
if is_cmp casn state && fenceless_get loc.state != state then
132+
if is_cmp casn state && fenceless_get (as_atomic loc) != state then
130133
`Before
131134
else verify casn gt
132135
| `Before -> `Before)
@@ -147,7 +150,7 @@ let rec determine casn status = function
147150
let status = if lt != NIL then determine casn status lt else status in
148151
if status < 0 then status
149152
else
150-
let current = Atomic.get loc.state in
153+
let current = Atomic.get (as_atomic loc) in
151154
if state == current then
152155
determine casn (status lor (1 + Bool.to_int (is_cmp casn state))) gt
153156
else
@@ -176,7 +179,7 @@ let rec determine casn status = function
176179
(match current.awaiters with
177180
| [] -> ()
178181
| awaiters -> record.awaiters <- awaiters);
179-
if Atomic.compare_and_set loc.state current state then
182+
if Atomic.compare_and_set (as_atomic loc) current state then
180183
determine casn (status lor a_cas) gt
181184
else determine casn status eq
182185
| #determined -> raise Exit
@@ -267,13 +270,13 @@ module Retry = struct
267270
end
268271

269272
let add_awaiter loc before awaiter =
270-
let state_old = fenceless_get loc.state in
273+
let state_old = fenceless_get (as_atomic loc) in
271274
let state_new =
272275
let awaiters = awaiter :: state_old.awaiters in
273276
{ before; after = before; casn = casn_after; awaiters }
274277
in
275278
before == eval state_old
276-
&& Atomic.compare_and_set loc.state state_old state_new
279+
&& Atomic.compare_and_set (as_atomic loc) state_old state_new
277280

278281
let[@tail_mod_cons] rec remove_first x' removed = function
279282
| [] ->
@@ -282,13 +285,13 @@ let[@tail_mod_cons] rec remove_first x' removed = function
282285
| x :: xs -> if x == x' then xs else x :: remove_first x' removed xs
283286

284287
let rec remove_awaiter loc before awaiter =
285-
let state_old = fenceless_get loc.state in
288+
let state_old = fenceless_get (as_atomic loc) in
286289
if before == eval state_old then
287290
let removed = ref true in
288291
let awaiters = remove_first awaiter removed state_old.awaiters in
289292
if !removed then
290293
let state_new = { before; after = before; casn = casn_after; awaiters } in
291-
if not (Atomic.compare_and_set loc.state state_old state_new) then
294+
if not (Atomic.compare_and_set (as_atomic loc) state_old state_new) then
292295
remove_awaiter loc before awaiter
293296

294297
let block loc before =
@@ -300,13 +303,13 @@ let block loc before =
300303
raise cancellation_exn)
301304

302305
let rec update_no_alloc backoff loc state f =
303-
let state' = fenceless_get loc.state in
306+
let state' = fenceless_get (as_atomic loc) in
304307
let before = eval state' in
305308
match f before with
306309
| after ->
307310
state.after <- after;
308311
if before == after then before
309-
else if Atomic.compare_and_set loc.state state' state then (
312+
else if Atomic.compare_and_set (as_atomic loc) state' state then (
310313
state.before <- after;
311314
resume_awaiters before state'.awaiters)
312315
else update_no_alloc (Backoff.once backoff) loc state f
@@ -315,23 +318,24 @@ let rec update_no_alloc backoff loc state f =
315318
update_no_alloc backoff loc state f
316319

317320
let rec exchange_no_alloc backoff loc state =
318-
let state' = fenceless_get loc.state in
321+
let state' = fenceless_get (as_atomic loc) in
319322
let before = eval state' in
320-
if before == state.after || Atomic.compare_and_set loc.state state' state then
321-
resume_awaiters before state'.awaiters
323+
if
324+
before == state.after || Atomic.compare_and_set (as_atomic loc) state' state
325+
then resume_awaiters before state'.awaiters
322326
else exchange_no_alloc (Backoff.once backoff) loc state
323327

324328
let is_obstruction_free casn =
325329
fenceless_get casn == (Mode.obstruction_free :> status)
326330
[@@inline]
327331

328332
let cas loc before state =
329-
let state' = fenceless_get loc.state in
333+
let state' = fenceless_get (as_atomic loc) in
330334
let before' = state'.before and after' = state'.after in
331335
((before == before' && before == after')
332336
|| before == if is_after state'.casn then after' else before')
333337
&& (before == state.after
334-
|| Atomic.compare_and_set loc.state state' state
338+
|| Atomic.compare_and_set (as_atomic loc) state' state
335339
&& resume_awaiters true state'.awaiters)
336340
[@@inline]
337341

@@ -342,11 +346,11 @@ module Loc = struct
342346
type 'a t = 'a loc
343347

344348
let make after =
345-
let state = Atomic.make @@ new_state after and id = Id.get_unique () in
346-
{ state; id }
349+
let _state = new_state after and id = Id.get_unique () in
350+
{ _state; id }
347351

348352
let get_id loc = loc.id [@@inline]
349-
let get loc = eval (Atomic.get loc.state)
353+
let get loc = eval (Atomic.get (as_atomic loc))
350354

351355
let rec get_as f loc =
352356
let before = get loc in
@@ -361,14 +365,14 @@ module Loc = struct
361365
cas loc before state
362366

363367
let update ?(backoff = Backoff.default) loc f =
364-
let state' = fenceless_get loc.state in
368+
let state' = fenceless_get (as_atomic loc) in
365369
let before = eval state' in
366370
match f before with
367371
| after ->
368372
if before == after then before
369373
else
370374
let state = new_state after in
371-
if Atomic.compare_and_set loc.state state' state then
375+
if Atomic.compare_and_set (as_atomic loc) state' state then
372376
resume_awaiters before state'.awaiters
373377
else update_no_alloc (Backoff.once backoff) loc state f
374378
| exception Retry.Later ->
@@ -387,7 +391,7 @@ module Loc = struct
387391
let decr ?backoff loc = update ?backoff loc dec |> ignore
388392

389393
let has_awaiters loc =
390-
let state = Atomic.get loc.state in
394+
let state = Atomic.get (as_atomic loc) in
391395
state.awaiters != []
392396
end
393397

@@ -430,7 +434,7 @@ module Op = struct
430434
| [] -> determine_for_owner casn cass
431435
| CAS (loc, before, after) :: rest ->
432436
if before == after && is_obstruction_free casn then
433-
let state = fenceless_get loc.state in
437+
let state = fenceless_get (as_atomic loc) in
434438
before == eval state && run (insert cass loc state) rest
435439
else
436440
run
@@ -439,7 +443,7 @@ module Op = struct
439443
in
440444
let (CAS (loc, before, after)) = first in
441445
if before == after && is_obstruction_free casn then
442-
let state = fenceless_get loc.state in
446+
let state = fenceless_get (as_atomic loc) in
443447
before == eval state
444448
&& run (CASN { loc; state; lt = NIL; gt = NIL; awaiters = [] }) rest
445449
else
@@ -455,7 +459,7 @@ module Xt = struct
455459
}
456460

457461
let update0 loc f xt lt gt =
458-
let state = fenceless_get loc.state in
462+
let state = fenceless_get (as_atomic loc) in
459463
let before = eval state in
460464
let after = f before in
461465
let state =

0 commit comments

Comments
 (0)