-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Hi, first of all thanks for contributing and maintaining this super nice library. This work is greatly appreciated.
I would like to open a discussion about a potential improvement to the library.
I work in a project where we have a clear separation of pure and non-pure crates. This allows for reuse of code across platform for purely logic code. Hyper is one of our core components.
One issue we are encountering is regarding timers. Indeed, this trait requires the caller to have access to std::time::Instant for sleep_until
, which is not something we can guarantee for various reasons I am not able to describe here. The sleep_until
method seems to be used internally for HTTP/2 keep-alives ultimately generating system calls in places where we would like to be syscall free.
Ideally, hyper should be able to delegate side-effects, like it does for the sockets operations - the Read/Write trait do not expose a dependency to a structure that forces the caller to do a system call like std::time::Instant
does.
My simple proposal is to make the trait instant agnostic. I think that there are two important aspect here:
- The Timer trait allows to define the instant type to use
sleep_until
depends on Self::Instant- Hyper requires a component implementing a trait abstracting how to get the current time via a
now()
method.
A very rudimentary proposal:
trait Timer {
type Instant;
fn sleep_until(&self, deadline: Self::Instant) -> Pin<Box<dyn Sleep>>;
// skipping sleep and reset ...
}
trait TimeFactory {
type Instant;
fn now(&self) -> Self::Instant;
fn epoch(&self) -> Self::Instant;
}
With the proposed approach, hyper won't have to rely on system calls to get an Instant if the calling code is not able to. In addition, the time could be mocked in test allowing a finer control and a faster test suite.
Thanks for your time