File: simple_cqs.ml

package info (click to toggle)
ocaml-eio 1.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,548 kB
  • sloc: ml: 14,608; ansic: 1,237; makefile: 25
file content (62 lines) | stat: -rw-r--r-- 1,720 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(* A queue built on cells.ml using the "simple" cancellation mode,
   where resuming a cancelled request does nothing instead of retrying. *)

module Make(Config : sig val segment_order : int end) = struct
  module Cell = struct
    type _ t =
      | Empty
      | Value of int
      | Waiting of (int -> unit)
      | Cancelled
      | Finished

    let init = Empty

    let segment_order = Config.segment_order

    let dump f = function
      | Empty -> Fmt.string f "Empty"
      | Value v -> Fmt.pf f "Value %d" v
      | Waiting _  -> Fmt.string f "Waiting"
      | Cancelled -> Fmt.string f "Cancelled"
      | Finished -> Fmt.string f "Finished"
  end

  module Cells = Cells.Make(Cell)

  let cancel (segment, cell) =
    match Atomic.get cell with
    | Cell.Waiting _ as prev ->
      if Atomic.compare_and_set cell prev Cancelled then (
        Cells.cancel_cell segment;
        true
      ) else (
        false
      )
    | Finished -> false
    | _ -> assert false

  let resume t v =
    let cell = Cells.next_resume t in
    if not (Atomic.compare_and_set cell Cell.Empty (Value v)) then (
      match Atomic.get cell with
      | Waiting w as prev ->
        if Atomic.compare_and_set cell prev Finished then w v
      (* else cancelled *)
      | Cancelled -> ()
      | Empty | Value _ | Finished -> assert false
    )

  let suspend t k =
    let segment, cell = Cells.next_suspend t in
    if Atomic.compare_and_set cell Cell.Empty (Waiting k) then Some (segment, cell)
    else (
      match Atomic.get cell with
      | Value v -> Atomic.set cell Finished; k v; None
      | Cancelled | Empty | Waiting _ | Finished -> assert false
    )

  let make = Cells.make

  let dump = Cells.dump
end