Saturn.Bounded_stackLock-free bounded stack.
This module implements a lock-free bounded stack based on Treiber's stack algorithm. Adding a capacity to this algorithm adds a general overhead to the operations, and thus, it is recommended to use the unbounded stack Saturn.Stack if neither the capacity nor the length function is needed.
val create : ?capacity:int -> unit -> 'a tcreate ~capacity () creates a new empty bounded stack with a maximum capacity of capacity. The default capacity value is Int.max_int.
val of_list_exn : ?capacity:int -> 'a list -> 'a tof_list_exn list creates a new Treiber stack from a list.
val length : 'a t -> intlength stack returns the number of elements currently in the stack.
val is_empty : 'a t -> boolis_empty stack returns true if the stack is empty, otherwise false.
val is_full : 'a t -> boolis_full stack returns true if the stack has reached capacity, otherwise false.
val peek_exn : 'a t -> 'apeek_exn stack returns the top element of the stack without removing it.
val peek_opt : 'a t -> 'a optionpeek_opt stack returns Some of the top element of the stack without removing it, or None if the stack is empty.
val pop_exn : 'a t -> 'apop_exn stack removes and returns the top element of the stack.
val pop_opt : 'a t -> 'a optionpop_opt stack removes and returns Some of the top element of the stack, or None if the stack is empty.
val drop_exn : 'a t -> unitdrop_exn stack removes the top element of the stack.
val pop_all : 'a t -> 'a listpop_all stack removes and returns all elements of the stack in LIFO order.
# open Saturn.Bounded_stack
# let t : int t = create ()
val t : int t = <abstr>
# try_push t 1
- : bool = true
# try_push t 2
- : bool = true
# try_push t 3
- : bool = true
# pop_all t
- : int list = [3; 2; 1]Raised when push_exn or push_all_exn is applied to a full stack.
val push_exn : 'a t -> 'a -> unitpush_exn stack element adds element to the top of the stack.
val try_push : 'a t -> 'a -> booltry_push stack element tries to add element to the top of the stack. Returns true if the element was successfully added, or false if the stack is full.
val push_all_exn : 'a t -> 'a list -> unitpush_all_exn stack elements adds all elements to the top of the stack.
val try_push_all : 'a t -> 'a list -> booltry_push_all stack elements tries to add all elements to the top of the stack. Returns true if the elements were successfully added, or false if the stack is full.
🐌 This is a linear-time operation on the size of elements.
# let t : int t = create ()
val t : int t = <abstr>
# try_push_all t [1; 2; 3; 4]
- : bool = true
# pop_opt t
- : int option = Some 4
# pop_opt t
- : int option = Some 3
# pop_all t
- : int list = [2; 1]val to_seq : 'a t -> 'a Stdlib.Seq.tWith Sequences
to_seq stack takes a snapshot of stack and returns its value from top to bottom.
🐌 This is a linear time operation.
val of_seq : ?capacity:int -> 'a Stdlib.Seq.t -> 'a tof_seq seq creates a stack from a seq. It must be finite.
val add_seq_exn : 'a t -> 'a Stdlib.Seq.t -> unitadd_seq_exn stack seq adds all elements of seq to the top of the stack. seq must be finite.
val try_add_seq : 'a t -> 'a Stdlib.Seq.t -> booltry_add_seq stack seq tries to add all elements of seq to the top of the stack. Returns true if the elements were successfully added, or false if the seq is too long to fit in the stack.
🐌 This is a linear-time operation.
An example top-level session:
# open Saturn.Bounded_stack
# let t : int t = create ()
val t : int t = <abstr>
# try_push t 42
- : bool = true
# push_exn t 1
- : unit = ()
# pop_exn t
- : int = 1
# peek_opt t
- : int option = Some 42
# pop_opt t
- : int option = Some 42
# pop_opt t
- : int option = None
# pop_exn t
Exception: Saturn__Bounded_stack.Empty.Note: The barrier is used in this example solely to make the results more interesting by increasing the likelihood of parallelism. Spawning a domain is a costly operation, especially compared to the relatively small amount of work being performed here. In practice, using a barrier in this manner is unnecessary.
# open Saturn.Bounded_stack
# let t :int t = create ()
val t : int t = <abstr>
# let barrier = Atomic.make 2
val barrier : int Atomic.t = <abstr>
# let pusher () =
Atomic.decr barrier;
while Atomic.get barrier != 0 do Domain.cpu_relax () done;
try_push_all t [1;2;3] |> ignore;
push_exn t 42;
push_exn t 12
val pusher : unit -> unit = <fun>
# let popper () =
Atomic.decr barrier;
while Atomic.get barrier != 0 do Domain.cpu_relax () done;
List.init 6 (fun i -> Domain.cpu_relax (); pop_opt t)
val popper : unit -> int option list = <fun>
# let domain_pusher = Domain.spawn pusher
val domain_pusher : unit Domain.t = <abstr>
# let domain_popper = Domain.spawn popper
val domain_popper : int option list Domain.t = <abstr>
# Domain.join domain_pusher
- : unit = ()
# Domain.join domain_popper
- : int option list = [Some 42; Some 3; Some 2; Some 1; None; Some 12]