Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
dllist.ml1 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176open Kcas type 'a t = { prev : 'a t Loc.t; next : 'a t Loc.t } type 'a node = { node_prev : 'a t Loc.t; node_next : 'a t Loc.t; value : 'a } external as_list : 'a node -> 'a t = "%identity" external as_node : 'a t -> 'a node = "%identity" let get { value; _ } = value [@@inline] let create () = let prev = Loc.make (Obj.magic ()) and next = Loc.make (Obj.magic ()) in let list = { prev; next } in Loc.set prev list; Loc.set next list; list let create_node ~prev ~next value = { node_prev = Loc.make prev; node_next = Loc.make next; value } module Xt = struct let remove ~xt node = let list = as_list node in let next = Xt.exchange ~xt list.next list in if next != list then ( let prev = Xt.exchange ~xt list.prev list in Xt.set ~xt next.prev prev; Xt.set ~xt prev.next next) let is_empty ~xt list = Xt.get ~xt list.prev == list let add_node_l ~xt node list = let next = Xt.get ~xt list.next in assert (Loc.fenceless_get node.node_prev == list); Loc.set node.node_next next; Xt.set ~xt list.next (as_list node); Xt.set ~xt next.prev (as_list node); node let add_l ~xt value list = let next = Xt.get ~xt list.next in let node = create_node ~prev:list ~next value in Xt.set ~xt list.next (as_list node); Xt.set ~xt next.prev (as_list node); node let add_node_r ~xt node list = let prev = Xt.get ~xt list.prev in Loc.set node.node_prev prev; assert (Loc.fenceless_get node.node_next == list); Xt.set ~xt list.prev (as_list node); Xt.set ~xt prev.next (as_list node); node let add_r ~xt value list = let prev = Xt.get ~xt list.prev in let node = create_node ~prev ~next:list value in Xt.set ~xt list.prev (as_list node); Xt.set ~xt prev.next (as_list node); node let take_opt_l ~xt list = let next = Xt.get ~xt list.next in if next == list then None else let node = as_node next in remove ~xt node; Some node.value let take_opt_r ~xt list = let prev = Xt.get ~xt list.prev in if prev == list then None else let node = as_node prev in remove ~xt node; Some node.value let take_blocking_l ~xt list = Xt.to_blocking ~xt (take_opt_l list) let take_blocking_r ~xt list = Xt.to_blocking ~xt (take_opt_r list) let transfer_l ~xt t1 t2 = let t1_next = Xt.exchange ~xt t1.next t1 in if t1_next != t1 then ( let t1_prev = Xt.exchange ~xt t1.prev t1 in let t2_next = Xt.exchange ~xt t2.next t1_next in Xt.set ~xt t2_next.prev t1_prev; Xt.set ~xt t1_next.prev t2; Xt.set ~xt t1_prev.next t2_next) let transfer_r ~xt t1 t2 = let t1_next = Xt.exchange ~xt t1.next t1 in if t1_next != t1 then ( let t1_prev = Xt.exchange ~xt t1.prev t1 in let t2_prev = Xt.exchange ~xt t2.prev t1_prev in Xt.set ~xt t2_prev.next t1_next; Xt.set ~xt t1_prev.next t2; Xt.set ~xt t1_next.prev t2_prev) let swap ~xt t1 t2 = let t1_next = Xt.get ~xt t1.next in if t1_next == t1 then transfer_l ~xt t2 t1 else let t2_prev = Xt.get ~xt t2.prev in if t2_prev == t2 then transfer_l ~xt t1 t2 else let t1_prev = Xt.exchange ~xt t1.prev t2_prev and t2_next = Xt.exchange ~xt t2.next t1_next in Xt.set ~xt t2.prev t1_prev; Xt.set ~xt t1.next t2_next; Xt.set ~xt t2_next.prev t1; Xt.set ~xt t2_prev.next t1; Xt.set ~xt t1_next.prev t2; Xt.set ~xt t1_prev.next t2 let[@tail_mod_cons] rec to_list_as_l ~xt f list node = if node == list then [] else f (as_node node) :: to_list_as_l ~xt f list (Xt.get ~xt node.next) let to_list_as_l ~xt f list = to_list_as_l ~xt f list (Xt.get ~xt list.next) let to_list_l ~xt list = to_list_as_l ~xt get list let to_nodes_l ~xt list = to_list_as_l ~xt Fun.id list let[@tail_mod_cons] rec to_list_as_r ~xt f list node = if node == list then [] else f (as_node node) :: to_list_as_r ~xt f list (Xt.get ~xt node.prev) let to_list_as_r ~xt f list = to_list_as_r ~xt f list (Xt.get ~xt list.prev) let to_list_r ~xt list = to_list_as_r ~xt get list let to_nodes_r ~xt list = to_list_as_r ~xt Fun.id list end let remove node = Kcas.Xt.commit { tx = Xt.remove node } let is_empty list = Loc.get list.prev == list let add_l value list = let node = create_node ~prev:list ~next:list value in Kcas.Xt.commit { tx = Xt.add_node_l node list } let add_r value list = let node = create_node ~prev:list ~next:list value in Kcas.Xt.commit { tx = Xt.add_node_r node list } let take_opt_l list = Kcas.Xt.commit { tx = Xt.take_opt_l list } let take_opt_r list = Kcas.Xt.commit { tx = Xt.take_opt_r list } let take_blocking_l list = Kcas.Xt.commit { tx = Xt.take_blocking_l list } let take_blocking_r list = Kcas.Xt.commit { tx = Xt.take_blocking_r list } let swap t1 t2 = Kcas.Xt.commit { tx = Xt.swap t1 t2 } let transfer_l t1 t2 = Kcas.Xt.commit { tx = Xt.transfer_l t1 t2 } let transfer_r t1 t2 = Kcas.Xt.commit { tx = Xt.transfer_r t1 t2 } let to_list_l list = Kcas.Xt.commit { tx = Xt.to_list_l list } let to_list_r list = Kcas.Xt.commit { tx = Xt.to_list_r list } let to_nodes_l list = Kcas.Xt.commit { tx = Xt.to_nodes_l list } let to_nodes_r list = Kcas.Xt.commit { tx = Xt.to_nodes_r list } exception Empty let take_l list = match take_opt_l list with None -> raise Empty | Some v -> v let take_r list = match take_opt_r list with None -> raise Empty | Some v -> v let take_all list = let copy = { prev = Loc.make list; next = Loc.make list } in let open Kcas in let tx ~xt = let prev = Xt.exchange ~xt list.prev list in if prev == list then ( Loc.set copy.prev copy; Loc.set copy.next copy) else let next = Xt.exchange ~xt list.next list in Xt.set ~xt prev.next copy; Xt.set ~xt next.prev copy; Loc.set copy.prev prev; Loc.set copy.next next in Xt.commit { tx }; copy