123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187open!Import(** An interface for queues that follows Base's conventions, as opposed to OCaml's
standard [Queue] module. *)moduletypeS=sigtype'at[@@deriving_inlinesexp,sexp_grammar]includeSexplib0.Sexpable.S1withtype'at:='atvalt_sexp_grammar:'aSexplib0.Sexp_grammar.t->'atSexplib0.Sexp_grammar.t[@@@end]includeIndexed_container.S1withtype'at:='at(** [singleton a] returns a queue with one element. *)valsingleton:'a->'at(** [of_list list] returns a queue [t] with the elements of [list] in the same order as
the elements of [list] (i.e. the first element of [t] is the first element of the
list). *)valof_list:'alist->'atvalof_array:'aarray->'at(** [init n ~f] is equivalent to [of_list (List.init n ~f)]. *)valinit:int->f:(int->'a)->'at(** [enqueue t a] adds [a] to the end of [t].*)valenqueue:'at->'a->unit(** [enqueue_all t list] adds all elements in [list] to [t] in order of [list]. *)valenqueue_all:'at->'alist->unit(** [dequeue t] removes and returns the front element of [t], if any. *)valdequeue:'at->'aoptionvaldequeue_exn:'at->'a(** [dequeue_and_ignore_exn t] removes the front element of [t], or raises if the queue
is empty. *)valdequeue_and_ignore_exn:'at->unit(** [drain t ~f ~while_] repeatedly calls [while_] on the head of [t], and if it returns
true then dequeues it and calls [f] on it. It stops when [t] is empty or [while_]
returns false. A common use case is tracking the sum of data in a recent time
interval: [t] contains timestamped data, [while_] checks for elements with an old
timestamp, and [f] subtracts data from the sum. *)valdrain:'at->f:('a->unit)->while_:('a->bool)->unit(** [peek t] returns but does not remove the front element of [t], if any. *)valpeek:'at->'aoptionvalpeek_exn:'at->'a(** [clear t] discards all elements from [t]. *)valclear:_t->unit(** [copy t] returns a copy of [t]. *)valcopy:'at->'atvalmap:'at->f:('a->'b)->'btvalmapi:'at->f:(int->'a->'b)->'bt(** Creates a new queue with elements equal to [List.concat_map ~f (to_list t)]. *)valconcat_map:'at->f:('a->'blist)->'btvalconcat_mapi:'at->f:(int->'a->'blist)->'bt(** [filter_map] creates a new queue with elements equal to [List.filter_map ~f (to_list
t)]. *)valfilter_map:'at->f:('a->'boption)->'btvalfilter_mapi:'at->f:(int->'a->'boption)->'bt(** [filter] is like [filter_map], except with [List.filter]. *)valfilter:'at->f:('a->bool)->'atvalfilteri:'at->f:(int->'a->bool)->'at(** [filter_inplace t ~f] removes all elements of [t] that don't satisfy [f]. If [f]
raises, [t] is unchanged. This is inplace in that it modifies [t]; however, it uses
space linear in the final length of [t]. *)valfilter_inplace:'at->f:('a->bool)->unitvalfilteri_inplace:'at->f:(int->'a->bool)->unitendmoduletypeQueue=sig(** A queue implemented with an array.
The implementation will grow the array as necessary. The array will
never automatically be shrunk, but the size can be interrogated and set
with [capacity] and [set_capacity].
Iteration functions ([iter], [fold], [map], [concat_map], [filter],
[filter_map], [filter_inplace], and some functions from [Container.S1])
will raise if the queue is modified during iteration.
Also see {!Linked_queue}, which has different performance characteristics. *)moduletypeS=Stype'at[@@deriving_inlinecompare~localize,globalize]includePpx_compare_lib.Comparable.S1withtype'at:='atincludePpx_compare_lib.Comparable.S_local1withtype'at:='atvalglobalize:('a->'a)->'at->'at[@@@end]includeSwithtype'at:='atincludeEqual.S1withtype'at:='atincludePpx_compare_lib.Equal.S_local1withtype'at:='atincludeInvariant.S1withtype'at:='at(** Create an empty queue. *)valcreate:?capacity:int(** default is [1]. *)->unit->_t(** [last t] returns the most recently enqueued element in [t], if any. *)vallast:'at->'aoptionvallast_exn:'at->'a(** Add an element to the front of the queue, as opposed to [enqueue] which adds to the
back of the queue. *)valenqueue_front:'at->'a->unit(** [dequeue_back t] removes and returns the back element of [t], if any. *)valdequeue_back:'at->'aoptionvaldequeue_back_exn:'at->'a(** [peek_back t] returns but does not remove the back element of [t], if any. *)valpeek_back:'at->'aoptionvalpeek_back_exn:'at->'a(** Transfers up to [len] elements from the front of [src] to the end of [dst], removing
them from [src]. It is an error if [len < 0].
Aside from a call to [set_capacity dst] if needed, runs in O([len]) time *)valblit_transfer:src:'at->dst:'at->?len:int(** default is [length src] *)->unit->unit(** [get t i] returns the [i]'th element in [t], where the 0'th element is at the front of
[t] and the [length t - 1] element is at the back. *)valget:'at->int->'avalset:'at->int->'a->unit(** Returns the current length of the backing array. *)valcapacity:_t->int(** [set_capacity t c] sets the capacity of [t]'s backing array to at least [max c (length
t)]. If [t]'s capacity changes, then this involves allocating a new backing array and
copying the queue elements over. [set_capacity] may decrease the capacity of [t], if
[c < capacity t]. *)valset_capacity:_t->int->unit(** Use [Iteration] to implement iteration functions that guard against mutation. *)moduleIteration:sigtype'aqueue:='at(** A token representing state from the beginning of an iteration. *)typet[@@immediate](** Capture state at the start of iteration. *)valstart:_queue->t(** [assert_no_mutation_since_start t queue] raises if any mutation has happened to
[queue] since [t] was created by [start queue]. Results are unspecified if you
call [assert_no_mutation_since_start] with a different queue from the one passed
to [start].
Call [assert_no_mutation_since_start] after each step of an iteration loop, before
checking if the queue is empty or advancing to the next element. This ensures
these read operations are consistent with the queue's state at the start of
iteration. *)valassert_no_mutation_since_start:t->_queue->unitendend