-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
IO timeout usability improvements #15802
Comments
And similarly a |
We also probably want these to not take integer milliseconds but some kind of time type. |
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 |
(Sorry I posted my comment on a wrong tree before.) I did a quick search for candidates for updating to use $ ack --ignore-dir llvm --ignore-dir test 'time.*u64' src/
src/libtime/lib.rs
71: pub fn mach_absolute_time() -> u64;
145: let ns_since_1601 = ((time.dwHighDateTime as u64 << 32) |
146: (time.dwLowDateTime as u64 << 0)) / 10;
175:pub fn precise_time_ns() -> u64 {
179: fn os_precise_time_ns() -> u64 {
195: fn os_precise_time_ns() -> u64 {
204: time * TIMEBASE.numer as u64 / TIMEBASE.denom as u64
209: fn os_precise_time_ns() -> u64 {
src/libcollections/vec.rs
2390: b.bytes = (times * src_len) as u64;
src/librbml/io.rs
187: b.bytes = (times * len) as u64;
src/libnative/io/file_windows.rs
216: fn set_timeout(&mut self, _t: Option<u64>) {}
217: fn set_read_timeout(&mut self, _t: Option<u64>) {}
218: fn set_write_timeout(&mut self, _t: Option<u64>) {}
480: created: stat.st_ctime as u64,
481: modified: stat.st_mtime as u64,
482: accessed: stat.st_atime as u64,
510:pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
src/libnative/io/pipe_windows.rs
270: pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
546: fn set_timeout(&mut self, timeout: Option<u64>) {
551: fn set_read_timeout(&mut self, timeout: Option<u64>) {
554: fn set_write_timeout(&mut self, timeout: Option<u64>) {
736: fn set_timeout(&mut self, timeout: Option<u64>) {
src/libnative/io/process.rs
127: fn set_timeout(&mut self, timeout: Option<u64>) {
src/libnative/io/util.rs
57:pub fn ms_to_timeval(ms: u64) -> libc::timeval {
64:pub fn ms_to_timeval(ms: u64) -> libc::timeval {
104: timeout_ms: u64) -> IoResult<()> {
151: timeout: u64) -> libc::c_int {
164: timeout: u64) -> libc::c_int {
src/libnative/io/mod.rs
167: timeout: Option<u64>)
193: timeout: Option<u64>) -> IoResult<Box<rtio::RtioPipe + Send>> {
256: fn fs_utime(&mut self, src: &CString, atime: u64,
257: mtime: u64) -> IoResult<()> {
src/libnative/io/net.rs
239: timeout: Option<u64>) -> IoResult<TcpStream> {
380: fn set_timeout(&mut self, timeout: Option<u64>) {
385: fn set_read_timeout(&mut self, timeout: Option<u64>) {
388: fn set_write_timeout(&mut self, timeout: Option<u64>) {
648: fn set_timeout(&mut self, timeout: Option<u64>) {
866: fn set_timeout(&mut self, timeout: Option<u64>) {
871: fn set_read_timeout(&mut self, timeout: Option<u64>) {
874: fn set_write_timeout(&mut self, timeout: Option<u64>) {
src/libnative/io/pipe_unix.rs
81: timeout: Option<u64>) -> IoResult<Inner> {
126: timeout: Option<u64>) -> IoResult<UnixStream> {
196: fn set_timeout(&mut self, timeout: Option<u64>) {
201: fn set_read_timeout(&mut self, timeout: Option<u64>) {
204: fn set_write_timeout(&mut self, timeout: Option<u64>) {
307: fn set_timeout(&mut self, timeout: Option<u64>) {
src/libnative/io/file_unix.rs
183: fn set_timeout(&mut self, _t: Option<u64>) {}
184: fn set_read_timeout(&mut self, _t: Option<u64>) {}
185: fn set_write_timeout(&mut self, _t: Option<u64>) {}
446: fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
462: created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
463: modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
464: accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
494:pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
src/libstd/io/fs.rs
805:pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> {
src/libstd/io/net/udp.rs
186: pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
194: pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
202: pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
src/libstd/io/net/tcp.rs
118: io.tcp_connect(addr, Some(timeout.num_milliseconds() as u64)).map(TcpStream::new)
228: pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
245: pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
272: pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
444: pub fn set_timeout(&mut self, ms: Option<u64>) { self.obj.set_timeout(ms); }
src/libstd/io/net/unix.rs
77: let s = io.unix_connect(&path.to_c_str(), Some(timeout.num_milliseconds() as u64));
109: pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
117: pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
125: pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
212: pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
src/libstd/io/process.rs
539: pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
src/libstd/io/mem.rs
564: b.bytes = (times * len) as u64;
src/librustrt/rtio.rs
192: timeout: Option<u64>) -> IoResult<Box<RtioTcpStream + Send>>;
200: timeout: Option<u64>) -> IoResult<Box<RtioPipe + Send>>;
224: fn fs_utime(&mut self, src: &CString, atime: u64, mtime: u64) ->
248: fn set_timeout(&mut self, timeout: Option<u64>);
264: fn set_timeout(&mut self, timeout_ms: Option<u64>);
265: fn set_read_timeout(&mut self, timeout_ms: Option<u64>);
266: fn set_write_timeout(&mut self, timeout_ms: Option<u64>);
290: fn set_timeout(&mut self, timeout_ms: Option<u64>);
291: fn set_read_timeout(&mut self, timeout_ms: Option<u64>);
292: fn set_write_timeout(&mut self, timeout_ms: Option<u64>);
318: fn set_timeout(&mut self, timeout: Option<u64>);
328: fn set_timeout(&mut self, timeout_ms: Option<u64>);
329: fn set_read_timeout(&mut self, timeout_ms: Option<u64>);
330: fn set_write_timeout(&mut self, timeout_ms: Option<u64>);
339: fn set_timeout(&mut self, timeout: Option<u64>);
src/librustuv/uvio.rs
143: fn tcp_connect(&mut self, addr: rtio::SocketAddr, timeout: Option<u64>)
259: fn fs_utime(&mut self, path: &CString, atime: u64, mtime: u64)
293: fn unix_connect(&mut self, path: &CString, timeout: Option<u64>)
src/librustuv/timeout.rs
112: pub fn set_timeout(&mut self, ms: Option<u64>,
235: mut self, obj: T, timeout: Option<u64>, io: &mut UvIoFactory,
src/librustuv/timer.rs
53: pub fn start(&mut self, f: uvll::uv_timer_cb, msecs: u64, period: u64) {
src/librustuv/file.rs
248: pub fn utime(loop_: &Loop, path: &CString, atime: u64, mtime: u64)
276: fn to_msec(stat: uvll::uv_timespec_t) -> u64 {
src/librustuv/process.rs
276: fn set_timeout(&mut self, timeout: Option<u64>) {
src/librustuv/net.rs
202: timeout: Option<u64>) -> Result<TcpWatcher, UvError> {
305: fn set_timeout(&mut self, timeout: Option<u64>) {
310: fn set_read_timeout(&mut self, ms: Option<u64>) {
322: fn set_write_timeout(&mut self, ms: Option<u64>) {
477: fn set_timeout(&mut self, ms: Option<u64>) {
793: fn set_timeout(&mut self, timeout: Option<u64>) {
798: fn set_read_timeout(&mut self, ms: Option<u64>) {
820: fn set_write_timeout(&mut self, ms: Option<u64>) {
src/librustuv/pipe.rs
89: pub fn connect(io: &mut UvIoFactory, name: &CString, timeout: Option<u64>)
175: fn set_timeout(&mut self, timeout: Option<u64>) {
180: fn set_read_timeout(&mut self, ms: Option<u64>) {
192: fn set_write_timeout(&mut self, ms: Option<u64>) {
315: fn set_timeout(&mut self, ms: Option<u64>) { |
cc me |
If no one else is working on this, I'll take a stab at it. |
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. |
@thestinger Do you know if this overhaul is happening before v1? This issue has been open for a while now. |
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 Please let me know if you would like to be involved in this effort! |
@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 |
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 In the 1.0 beta timeframe, perhaps it is best to not stabilize methods taking a timeout (i.e., leave them as I will discuss this with the team and let you know what the best avenue forward looks to be. |
@aturon here's an option to help mitigate the absolute time issues: Define an |
@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 |
@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? |
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 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). |
@aturon Thanks for the progress update. I'm still interested in helping. |
@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 Personally I'm hesitant to follow Win32 timeout design which is so sloppy:
|
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. |
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. |
I'm going to close this since it currently relates only to |
The current timeout API on the various stream implementations behaves as a deadline vs. a timeout setting. I propose the following.
set_timeout
->set_deadline
. (as well as the read and write variants).set_deadline
to a trait (for example:ReadDeadline
andWriteDeadline
)TimedReader
andTimedWriter
that operate as follows:cc @alexcrichton
The text was updated successfully, but these errors were encountered: