Skip to content

Commit 2de717e

Browse files
committed
More complex counter logic
1 parent bef8855 commit 2de717e

File tree

1 file changed

+34
-11
lines changed

1 file changed

+34
-11
lines changed

lib/picos_std.sync/conditions.ml

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ let create ?padded () = Awaitable.make ?padded 0
88
let[@inline] wait t lock ~acquire ~release =
99
let before = Awaitable.get t in
1010
release lock;
11-
let lock_forbidden lock =
11+
let lock_forbidden lock ~acquire =
1212
let fiber = Fiber.current () in
1313
let forbid = Fiber.exchange fiber ~forbid:true in
1414
match acquire lock with
@@ -19,17 +19,40 @@ let[@inline] wait t lock ~acquire ~release =
1919
Fiber.set fiber ~forbid;
2020
Printexc.raise_with_backtrace exn bt
2121
in
22-
match if Awaitable.get t == before then Awaitable.await t before with
23-
| () -> lock_forbidden lock
24-
| exception exn ->
25-
let bt = Printexc.get_raw_backtrace () in
26-
lock_forbidden lock;
27-
Printexc.raise_with_backtrace exn bt
22+
let await t lock ~acquire before =
23+
match if Awaitable.get t == before then Awaitable.await t before with
24+
| () ->
25+
let before = Awaitable.get t in
26+
if before land 1 = 0 then begin
27+
let after = before lor 1 in
28+
if
29+
(not (Awaitable.compare_and_set t before after))
30+
&& Awaitable.get t land 1 = 0
31+
then Awaitable.signal t
32+
end;
33+
lock_forbidden lock ~acquire
34+
| exception exn ->
35+
let bt = Printexc.get_raw_backtrace () in
36+
lock_forbidden lock ~acquire;
37+
Printexc.raise_with_backtrace exn bt
38+
in
39+
if before land 1 = 0 then
40+
let after = before lor 1 in
41+
if Awaitable.compare_and_set t before after || Awaitable.get t == after then
42+
await t lock ~acquire after
43+
else lock_forbidden lock ~acquire
44+
else await t lock ~acquire before
2845

2946
let signal t =
30-
Awaitable.incr t;
31-
Awaitable.signal t
47+
let prior = Awaitable.fetch_and_add t 2 in
48+
if prior land 1 <> 0 then begin
49+
if Awaitable.compare_and_set t (prior + 2) (prior + 1) then ();
50+
Awaitable.signal t
51+
end
3252

3353
let broadcast t =
34-
Awaitable.incr t;
35-
Awaitable.broadcast t
54+
let prior = Awaitable.fetch_and_add t 2 in
55+
if prior land 1 <> 0 then begin
56+
if Awaitable.compare_and_set t (prior + 2) (prior + 1) then ();
57+
Awaitable.broadcast t
58+
end

0 commit comments

Comments
 (0)