-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Name of expire
is misleading
#6
Comments
I'm sorry for the misunderstanding. The implementation is based off section 6B in this paper, and in general is how timer wheels work. The paper talks about a number of different strategies and it's possible that a timer wheel may not be what you want. It sounds to me like what your looking for is a heap or list based priority queue for timers. Then you can call it at arbitrary times and get all expired timers in an iteration over the front of the queue. The problem with this in general is that there is no real accuracy in when the timers should expire and when they do. They are just guaranteed to expire some time after the duration of the timer. The purpose of the timer wheel is to allow a minimal amount of overhead for determining when a large amount of timers can expire simultaneously. Specifically I use it to track network read or write timeouts. A large number of processes can set a timeout of 5 seconds and get notified very shortly after five seconds that they have expired, with a precision of 10ms or so. Without migration as in #1 there is no work that must be done on expiration other than to alert the process of the timeout and cleanup any references in the cancel hashmap. There's also no need to make a syscall to get the current time, which can be a somewhat expensive operation. But most importantly it's cheap to create and stop a timer, as it doesn't require traversing a list or heap. It may be that the I actually disagree that using |
Yeah, I don't blame I think As for using loop {
for expired in wheel.expire() {
// do something with expired
}
do_some_work();
} If let mut wheel = CopyWheel::new(vec![Resolution::ms]);
wheel.start("foo", time::Duration::from_millis(5));
thread::sleep(time::Duration::from_secs(1));
println!("{:?}", wheel.expire().next()); This code will not print |
Ah! I see where you are coming from. Yes, this is a very good point, that I did realize when building this. I didn't worry too much about this in general because I have a thread where all it does is wait for epoll timeouts then places the expired timer ids on a channel where the real work is done elsewhere. That way timers fire on time. There can of course be exceptions but it seems good enough for my use case. I will change the name to |
I completely misunderstood the semantics of
expire
. I assumed that every time I call it, it will give me any expired timers based on the current time. However, after reading the code (and re-reading the top-level documentation), this does not seem to be the case. Instead, it seems likeexpire
is more like atick
function that must be called exactly every resolution time units, and will return any timers that expired that time unit, which is a very different interface from what I had in mind.For me personally, this probably means that
ferris
isn't for me; I specifically want it to work with wall-clock time without requiring exactly regular calls toexpire
. That doesn't mean thatferris
is bad in any way (I partially understand why the interface is this way), but I do think this fact need to be clearly stated, and be reinforced by the method names and type signatures. For example, usingDuration
is misleading when the methods (again, unless I've misunderstood) do not actually use wall-clock time for anything. Instead, it's more like "number of ticks", which is just ausize
.The text was updated successfully, but these errors were encountered: