|
1 | 1 | (** Treiber's Lock Free stack *)
|
2 | 2 |
|
3 |
| -type 'a node = Nil | Next of 'a * 'a node |
4 |
| -type 'a t = { head : 'a node Atomic.t } |
| 3 | +type 'a node = Nil | Cons of { value : 'a; tail : 'a node } |
| 4 | +type 'a t = 'a node Atomic.t |
5 | 5 |
|
6 |
| -let create () = |
7 |
| - let head = Nil in |
8 |
| - { head = Atomic.make head } |
| 6 | +let create () = Atomic.make Nil |> Multicore_magic.copy_as_padded |
| 7 | +let is_empty t = Atomic.get t == Nil |
9 | 8 |
|
10 |
| -let is_empty q = match Atomic.get q.head with Nil -> true | Next _ -> false |
| 9 | +let rec push t value backoff = |
| 10 | + let tail = Atomic.get t in |
| 11 | + let cons = Cons { value; tail } in |
| 12 | + if not (Atomic.compare_and_set t tail cons) then |
| 13 | + push t value (Backoff.once backoff) |
11 | 14 |
|
12 |
| -let rec push backoff q v = |
13 |
| - let head = Atomic.get q.head in |
14 |
| - let new_node = Next (v, head) in |
15 |
| - if Atomic.compare_and_set q.head head new_node then () |
16 |
| - else |
17 |
| - let backoff = Backoff.once backoff in |
18 |
| - push backoff q v |
19 |
| - |
20 |
| -let push q v = push Backoff.default q v |
| 15 | +let push t value = push t value Backoff.default |
21 | 16 |
|
22 | 17 | exception Empty
|
23 | 18 |
|
24 |
| -let rec pop backoff q = |
25 |
| - let s = Atomic.get q.head in |
26 |
| - match s with |
27 |
| - | Nil -> raise Empty |
28 |
| - | Next (v, next) -> |
29 |
| - if Atomic.compare_and_set q.head s next then v |
30 |
| - else |
31 |
| - let backoff = Backoff.once backoff in |
32 |
| - pop backoff q |
33 |
| - |
34 |
| -let pop q = pop Backoff.default q |
35 |
| - |
36 |
| -let rec pop_opt backoff q = |
37 |
| - let s = Atomic.get q.head in |
38 |
| - match s with |
39 |
| - | Nil -> None |
40 |
| - | Next (v, next) -> |
41 |
| - if Atomic.compare_and_set q.head s next then Some v |
42 |
| - else |
43 |
| - let backoff = Backoff.once backoff in |
44 |
| - pop_opt backoff q |
45 |
| - |
46 |
| -let pop_opt q = pop_opt Backoff.default q |
| 19 | +type ('a, _) poly = Option : ('a, 'a option) poly | Value : ('a, 'a) poly |
| 20 | + |
| 21 | +let rec pop_as : type a r. a t -> Backoff.t -> (a, r) poly -> r = |
| 22 | + fun t backoff poly -> |
| 23 | + match Atomic.get t with |
| 24 | + | Nil -> begin match poly with Option -> None | Value -> raise Empty end |
| 25 | + | Cons cons_r as cons -> |
| 26 | + if Atomic.compare_and_set t cons cons_r.tail then |
| 27 | + match poly with Option -> Some cons_r.value | Value -> cons_r.value |
| 28 | + else pop_as t (Backoff.once backoff) poly |
| 29 | + |
| 30 | +let pop t = pop_as t Backoff.default Value |
| 31 | +let pop_opt t = pop_as t Backoff.default Option |
0 commit comments