Timing_wheel
module Alarm_precision : sig ... end
val sexp_of_t : ('a -> Ppx_sexp_conv_lib.Sexp.t) -> 'a t -> Ppx_sexp_conv_lib.Sexp.t
type 'a timing_wheel = 'a t
type 'a t_now = 'a t
<:sexp_of< _ t_now >>
displays only now t
, not all the alarms.
val sexp_of_t_now : ('a -> Ppx_sexp_conv_lib.Sexp.t) -> 'a t_now -> Ppx_sexp_conv_lib.Sexp.t
module Interval_num : sig ... end
module Alarm : sig ... end
include Core_kernel.Invariant.S1 with type 'a t := 'a t
val invariant : ('a -> unit) -> 'a t -> unit
module Level_bits : sig ... end
module Config : sig ... end
val create : config:Config.t -> start:Core_kernel.Time_ns.t -> 'a t
create ~config ~start
creates a new timing wheel with current time start
. create
raises if start < Time_ns.epoch
. For a fixed level_bits
, a smaller (i.e. more precise) alarm_precision
decreases the representable range of times/keys and increases the constant factor for advance_clock
.
val alarm_precision : _ t -> Core_kernel.Time_ns.Span.t
Accessors
val now : _ t -> Core_kernel.Time_ns.t
val start : _ t -> Core_kernel.Time_ns.t
One can think of a timing wheel as a set of alarms. Here are various container functions along those lines.
val is_empty : _ t -> bool
val length : _ t -> int
val interval_num : _ t -> Core_kernel.Time_ns.t -> Interval_num.t
interval_num t time
returns the number of the interval that time
is in, where 0
is the interval that starts at Time_ns.epoch
. interval_num
raises if Time_ns.( < ) time Time_ns.epoch
.
val now_interval_num : _ t -> Interval_num.t
now_interval_num t = interval_num t (now t)
.
val interval_num_start : _ t -> Interval_num.t -> Core_kernel.Time_ns.t
interval_num_start t n
is the start of the n
'th interval in t
, i.e. n * alarm_precision t
after the epoch.
interval_start t time
is the start of the half-open interval containing time
, i.e.:
interval_num_start t (interval_num t time)
val interval_start : _ t -> Core_kernel.Time_ns.t -> Core_kernel.Time_ns.t
interval_start
raises in the same cases that interval_num
does.
val advance_clock : 'a t -> to_:Core_kernel.Time_ns.t -> handle_fired:('a Alarm.t -> unit) -> unit
advance_clock t ~to_ ~handle_fired
advances t
's clock to to_
. It fires and removes all alarms a
in t
with Time_ns.(<) (Alarm.at t a) (interval_start t
to_)
, applying handle_fired
to each such a
.
If to_ <= now t
, then advance_clock
does nothing.
advance_clock
fails if to_
is too far in the future to represent.
Behavior is unspecified if handle_fired
accesses t
in any way other than Alarm
functions.
fire_past_alarms t ~handle_fired
fires and removes all alarms a
in t
with Time_ns.( <= ) (Alarm.at t a) (now t)
, applying handle_fired
to each such a
.
fire_past_alarms
visits all alarms in interval now_interval_num
, to check their Alarm.at
.
Behavior is unspecified if handle_fired
accesses t
in any way other than Alarm
functions.
val max_allowed_alarm_time : _ t -> Core_kernel.Time_ns.t
max_allowed_alarm_time t
returns the greatest at
that can be supplied to add
. max_allowed_alarm_time
is not constant; its value increases as now t
increases.
val min_allowed_alarm_interval_num : _ t -> Interval_num.t
min_allowed_alarm_interval_num t = now_interval_num t
val max_allowed_alarm_interval_num : _ t -> Interval_num.t
max_allowed_alarm_interval_num t = interval_num t (max_allowed_alarm_time t)
val add : 'a t -> at:Core_kernel.Time_ns.t -> 'a -> 'a Alarm.t
add t ~at a
adds a new value a
to t
and returns an alarm that can later be supplied to remove
the alarm from t
. add
raises if interval_num t at <
now_interval_num t || at > max_allowed_alarm_time t
.
val add_at_interval_num : 'a t -> at:Interval_num.t -> 'a -> 'a Alarm.t
add_at_interval_num t ~at a
is equivalent to add t ~at:(interval_num_start t at)
a
.
remove t alarm
removes alarm
from t
. remove
raises if not (mem t
alarm)
.
val reschedule : 'a t -> 'a Alarm.t -> at:Core_kernel.Time_ns.t -> unit
reschedule t alarm ~at
mutates alarm
so that it will fire at at
, i.e. so that Alarm.at t alarm = at
. reschedule
raises if not (mem t alarm)
or if at
is an invalid time for t
, in the same situations that add
raises.
val reschedule_at_interval_num : 'a t -> 'a Alarm.t -> at:Interval_num.t -> unit
reschedule_at_interval_num t alarm ~at
is equivalent to:
reschedule t alarm ~at:(interval_num_start t at)
val clear : _ t -> unit
clear t
removes all alarms from t
.
val min_alarm_interval_num : _ t -> Interval_num.t option
min_alarm_interval_num t
is the minimum Alarm.interval_num
of all alarms in t
.
val min_alarm_interval_num_exn : _ t -> Interval_num.t
min_alarm_interval_num_exn t
is like min_alarm_interval_num
, except it raises if is_empty t
.
val max_alarm_time_in_min_interval : 'a t -> Core_kernel.Time_ns.t option
max_alarm_time_in_min_interval t
returns the maximum Alarm.at
over all alarms in t
whose Alarm.interval_num
is min_alarm_interval_num t
. This function is useful for advancing to the min_alarm_interval_num
of a timing wheel and then calling fire_past_alarms
to fire the alarms in that interval. That is useful when simulating time, to ensure that alarms are processed in order.
val max_alarm_time_in_min_interval_exn : 'a t -> Core_kernel.Time_ns.t
max_alarm_time_in_min_interval_exn t
is like max_alarm_time_in_min_interval
, except that it raises if is_empty t
.
val next_alarm_fires_at : _ t -> Core_kernel.Time_ns.t option
next_alarm_fires_at t
returns the minimum time to which the clock can be advanced such that an alarm will fire, or None
if t
has no alarms (or all alarms are in the max interval, and hence cannot fire). If next_alarm_fires_at t = Some next
, then for the minimum alarm time min
that occurs in t
, it is guaranteed that: next - alarm_precision t <= min < next
.
val next_alarm_fires_at_exn : _ t -> Core_kernel.Time_ns.t
next_alarm_fires_at_exn
is like next_alarm_fires_at
, except that it raises if is_empty t
.
module Private : sig ... end