Repository navigation
Closed
Description
The current timeout API on the various stream implementations behaves as a deadline vs. a timeout setting. I propose the following.
- Rename
set_timeout->set_deadline. (as well as the read and write variants). - Move
set_deadlineto a trait (for example:ReadDeadlineandWriteDeadline) - Provide
TimedReaderandTimedWriterthat operate as follows:
/// Various network related helpers
use std::io::{Reader, Writer, IoResult};
use std::io::net::unix::UnixStream;
use util::Duration;
pub trait ReadDeadline {
fn set_read_deadline(&mut self, timeout_ms: Option<u64>);
}
impl ReadDeadline for UnixStream {
fn set_read_deadline(&mut self, timeout_ms: Option<u64>) {
self.set_read_timeout(timeout_ms);
}
}
pub trait WriteDeadline {
fn set_write_deadline(&mut self, timeout_ms: Option<u64>);
}
impl WriteDeadline for UnixStream {
fn set_write_deadline(&mut self, timeout_ms: Option<u64>) {
self.set_write_timeout(timeout_ms);
}
}
pub struct TimedReader<R> {
reader: R,
timeout_ms: u64
}
impl<R: Reader + ReadDeadline> TimedReader<R> {
pub fn new(reader: R, timeout_ms: u64) -> TimedReader<R> {
TimedReader {
reader: reader,
timeout_ms: timeout_ms
}
}
}
impl<R: Reader + ReadDeadline> Reader for TimedReader<R> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
self.reader.set_read_deadline(Some(self.timeout_ms));
self.reader.read(buf)
}
}
pub struct TimedWriter<W> {
writer: W,
timeout_ms: u64
}
impl<W: Writer + WriteDeadline> TimedWriter<W> {
pub fn new(writer: W, timeout_ms: u64) -> TimedWriter<W> {
TimedWriter {
writer: writer,
timeout_ms: timeout_ms
}
}
}
impl<W: Writer + WriteDeadline> Writer for TimedWriter<W> {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
self.writer.set_write_deadline(Some(self.timeout_ms));
self.writer.write(buf)
}
}Metadata
Metadata
Assignees
Labels
No labels
Activity
tomaka commentedon Jul 22, 2014
And similarly a
AcceptDeadlinebrson commentedon Jul 31, 2014
We also probably want these to not take integer milliseconds but some kind of time type.
conradkleinespel commentedon Aug 31, 2014
Would love to see this implemented too. Anyway I can help?
Just for the sake of completeness, would be good to add support for this to
std::io::net::tcp::TcpStreamandstd::io::net::udp::UdpSocket.nodakai commentedon Sep 10, 2014
(Sorry I posted my comment on a wrong tree before.) I did a quick search for candidates for updating to use
Durationinstead of number of milliseconds etc. How many of them can be updated to useDurationwithout adding more dependency? I really want nice and stable API on I/O timeout.aturon commentedon Oct 1, 2014
cc me
murarth commentedon Oct 20, 2014
If no one else is working on this, I'll take a stab at it.
thestinger commentedon Oct 20, 2014
It's a bad time to start working on this because nearly all of this stuff is going to get an overhaul. It would make the most sense to implement it as part of a major rewrite.
conradkleinespel commentedon Nov 23, 2014
@thestinger Do you know if this overhaul is happening before v1? This issue has been open for a while now.
aturon commentedon Nov 23, 2014
@conradkleinespel
The overhaul is part of the runtime removal project. The first step is complete: removing rustuv, rtio, and the runtime scheduling abstractions has all landed. We're now revisiting the APIs previously built on the runtime system, including thread-local storage, sync, the
std::taskmodule, and afterwards,std::ioandstd::os.Please let me know if you would like to be involved in this effort!
nodakai commentedon Nov 23, 2014
@aturon I'm very interested in this, partily because I frequently write networking code with timeout in C++ and am hoping Rust to become its superiror alternative.
But I'm concerned about removal of
libtimefrom the stdlib. Pthread API with timeout are all based on absolute time which is only offered bylibtimeright now rather than relative time offered bystd::duration. The design decision behind Pthread disagrees with Alex'ssync-rswhich is based onstd::duration.aturon commentedon Nov 23, 2014
Thanks @nodakai. (And @conradkleinespel, I see you offered to help a little ways back).
I will be in touch ASAP about the plans here and ways that both of you might be able to help with design or implementation work.
As far as time goes, the reason
libtimewas moved out of the distro is that the API has gotten relatively little attention and likely needs substantial revision before moving intostd. (Note thatDurationhas its own problems, as well.)In the 1.0 beta timeframe, perhaps it is best to not stabilize methods taking a timeout (i.e., leave them as
#[unstable]; we may want to keep our options open here and put more effort into the underlying time representation.I will discuss this with the team and let you know what the best avenue forward looks to be.
sfackler commentedon Nov 23, 2014
@aturon here's an option to help mitigate the absolute time issues: Define an
AbsoluteTimetrait (or whatever), and have the relevant methods abstract over that. The standard library can have animpl AbsoluteTime for uint. libtime can have an impl as well. Then when we end up with a quality time library and want to move it into libstd we can just impl the trait for that and be good to go.alexcrichton commentedon Nov 23, 2014
@nodakai remember though that pthreads isn't the end-all-be-all of API design. My in-progress sync-rs for example uses relative timeouts because
Durationis already in the standard library and that's the only api Windows exposes. There are pros and cons either way, but neither is a silver bullet from what I've seen.aturon commentedon Nov 23, 2014
@alexcrichton What did you think about the point made in the linked posix docs about the rationale, though, namely that you can reliably build relative from absolute but not the other way around?
alexcrichton commentedon Nov 23, 2014
Someone's gotta lose in this paradigm choice because posix implements it one way and Windows implements it another. I don't personally advocate for either side, but I prefer whatever can give us a clean API today, which is quite easily gained with a
Durationtoday.I'm not sure I quite understand where it says that a relative timeout can be implemented on top of an absolute timeout, however. If I would like to sleep for at most 5ms inside of wait, then it's semantically different to take the absolute time, add 5ms, and sleep until that time. There's no actual guarantee that you slept in the call to wait for 5ms (preemptions, extra code, etc before the call to wait).
conradkleinespel commentedon Nov 25, 2014
@aturon Thanks for the progress update. I'm still interested in helping.
nodakai commentedon Nov 27, 2014
@alexcrichton As you observed, the rationale section of Pthread isn't an absolute proof that joining the "absolute time clan" is the only viable option for us. But still, POSIX is much better designed than Win32 API and I believe it will benefit us to follow it closely.
For example we will never be free from spurious wakeups with a condition variable. Sleeping with timeout of 50 ms might end up with a spurious wakeup only after 10 ms. Then we would typically want to sleep for 40 ms again. That can only be done by recording the absolute time just before we issue
timedwait(). We definitely need sort of absolute time anyways.Personally I'm hesitant to follow Win32 timeout design which is so sloppy:
thestinger commentedon Nov 27, 2014
Rust should be able to do at least as well as C++11, which has a thread API heavily based on POSIX threads but extends it with convenience methods to handle the looping for spurious wakeups and more.
thestinger commentedon Nov 27, 2014
The Windows condition variable API is broken and is not something that should be copied. An API using a relative time needs to return the elapsed time if it wakes up early.
aturon commentedon Feb 16, 2015
I'm going to close this since it currently relates only to
old_io, and the story for the new IO system will be fleshed out in a new RFC (which will likely be based on timeouts rather than deadlines.)