forked from ocaml-multicore/eio
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Based on PR ocaml-multicore#308 by Bikal Lem.
- Loading branch information
Showing
16 changed files
with
270 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,111 @@ | ||
open Eio.Std | ||
|
||
type t = < | ||
Eio.Time.clock; | ||
advance : unit; | ||
set_time : float -> unit; | ||
> | ||
|
||
module Key = struct | ||
type t = < > | ||
let compare = compare | ||
end | ||
module type S = sig | ||
type time | ||
|
||
type t = < | ||
time Eio.Time.clock_base; | ||
advance : unit; | ||
set_time : time -> unit; | ||
> | ||
|
||
module Job = struct | ||
type t = { | ||
time : float; | ||
resolver : unit Promise.u; | ||
} | ||
val make : unit -> t | ||
val advance : t -> unit | ||
val set_time : t -> time -> unit | ||
end | ||
|
||
let compare a b = Float.compare a.time b.time | ||
module type TIME = sig | ||
type t | ||
val zero : t | ||
val compare : t -> t -> int | ||
val pp : t Fmt.t | ||
end | ||
|
||
module Q = Psq.Make(Key)(Job) | ||
module Make(T : TIME) : S with type time := T.t = struct | ||
type t = < | ||
T.t Eio.Time.clock_base; | ||
advance : unit; | ||
set_time : T.t -> unit; | ||
> | ||
|
||
module Key = struct | ||
type t = < > | ||
let compare = compare | ||
end | ||
|
||
module Job = struct | ||
type t = { | ||
time : T.t; | ||
resolver : unit Promise.u; | ||
} | ||
|
||
let compare a b = T.compare a.time b.time | ||
end | ||
|
||
module Q = Psq.Make(Key)(Job) | ||
|
||
let make () = | ||
object (self) | ||
inherit [T.t] Eio.Time.clock_base | ||
|
||
let make () = | ||
object (self) | ||
inherit Eio.Time.clock | ||
val mutable now = T.zero | ||
val mutable q = Q.empty | ||
|
||
val mutable now = 0.0 | ||
val mutable q = Q.empty | ||
method now = now | ||
|
||
method now = now | ||
method sleep_until time = | ||
if T.compare time now <= 0 then Fiber.yield () | ||
else ( | ||
let p, r = Promise.create () in | ||
let k = object end in | ||
q <- Q.add k { time; resolver = r } q; | ||
try | ||
Promise.await p | ||
with Eio.Cancel.Cancelled _ as ex -> | ||
q <- Q.remove k q; | ||
raise ex | ||
) | ||
|
||
method sleep_until time = | ||
if time <= now then Fiber.yield () | ||
else ( | ||
let p, r = Promise.create () in | ||
let k = object end in | ||
q <- Q.add k { time; resolver = r } q; | ||
try | ||
Promise.await p | ||
with Eio.Cancel.Cancelled _ as ex -> | ||
q <- Q.remove k q; | ||
raise ex | ||
) | ||
method set_time time = | ||
let rec drain () = | ||
match Q.min q with | ||
| Some (_, v) when T.compare v.time time <= 0 -> | ||
Promise.resolve v.resolver (); | ||
q <- Option.get (Q.rest q); | ||
drain () | ||
| _ -> () | ||
in | ||
drain (); | ||
now <- time; | ||
traceln "mock time is now %a" T.pp now | ||
|
||
method set_time time = | ||
let rec drain () = | ||
method advance = | ||
match Q.min q with | ||
| Some (_, v) when v.time <= time -> | ||
Promise.resolve v.resolver (); | ||
q <- Option.get (Q.rest q); | ||
drain () | ||
| _ -> () | ||
in | ||
drain (); | ||
now <- time; | ||
traceln "mock time is now %g" now | ||
|
||
method advance = | ||
match Q.min q with | ||
| None -> invalid_arg "No further events scheduled on mock clock" | ||
| Some (_, v) -> self#set_time v.time | ||
end | ||
| None -> invalid_arg "No further events scheduled on mock clock" | ||
| Some (_, v) -> self#set_time v.time | ||
end | ||
|
||
let set_time (t:t) time = t#set_time time | ||
let advance (t:t) = t#advance | ||
end | ||
|
||
module Old_time = struct | ||
type t = float | ||
let compare = Float.compare | ||
let pp f x = Fmt.pf f "%g" x | ||
let zero = 0.0 | ||
end | ||
|
||
module Mono_time = struct | ||
type t = Mtime.t | ||
let compare = Mtime.compare | ||
let zero = Mtime.of_uint64_ns 0L | ||
|
||
let pp f t = | ||
let s = Int64.to_float (Mtime.to_uint64_ns t) /. 1e9 in | ||
Fmt.pf f "%g" s | ||
end | ||
|
||
module Mono = Make(Mono_time) | ||
|
||
let set_time (t:t) time = t#set_time time | ||
let advance (t:t) = t#advance | ||
include Make(Old_time) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,25 @@ | ||
type t = < | ||
Eio.Time.clock; | ||
advance : unit; | ||
set_time : float -> unit; | ||
> | ||
module type S = sig | ||
type time | ||
|
||
val make : unit -> t | ||
(** [make ()] is a new clock. | ||
type t = < | ||
time Eio.Time.clock_base; | ||
advance : unit; | ||
set_time : time -> unit; | ||
> | ||
|
||
The time is initially set to 0.0 and doesn't change except when you call {!advance} or {!set_time}. *) | ||
val make : unit -> t | ||
(** [make ()] is a new clock. | ||
val advance : t -> unit | ||
(** [advance t] sets the time to the next scheduled event (adding any due fibers to the run queue). | ||
@raise Invalid_argument if nothing is scheduled. *) | ||
The time is initially set to 0.0 and doesn't change except when you call {!advance} or {!set_time}. *) | ||
|
||
val set_time : t -> float -> unit | ||
(** [set_time t time] sets the time to [time] (adding any due fibers to the run queue). *) | ||
val advance : t -> unit | ||
(** [advance t] sets the time to the next scheduled event (adding any due fibers to the run queue). | ||
@raise Invalid_argument if nothing is scheduled. *) | ||
|
||
val set_time : t -> time -> unit | ||
(** [set_time t time] sets the time to [time] (adding any due fibers to the run queue). *) | ||
end | ||
|
||
include S with type time := float | ||
|
||
module Mono : S with type time := Mtime.t |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.