-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Amend RFC 517: Add material on deadlines #577
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,7 +44,8 @@ follow-up PRs against this RFC. | |
* [Proposed organization] | ||
* [Revising `Reader` and `Writer`] (stub) | ||
* [String handling] (stub) | ||
* [Deadlines] (stub) | ||
* [Deadlines] | ||
* [Timeouts versus deadlines] | ||
* [Splitting streams and cancellation] (stub) | ||
* [Modules] | ||
* [core::io] (stub) | ||
|
@@ -457,7 +458,94 @@ counts, arguments to `main`, and so on). | |
## Deadlines | ||
[Deadlines]: #deadlines | ||
|
||
> To be added in a follow-up PR. | ||
Most blocking system operations can take a timeout or a deadline | ||
(depending on the platform) for completion, and it's important that | ||
Rusts IO APIs offer the same capability. This poses a bit of a | ||
challenge, however, because adding variants to all of the blocking | ||
APIs would significantly increase the API surface, while taking an | ||
`Option` argument would decrease their ergonomics. | ||
|
||
The current solution is to offer `set_timeout` methods on various IO | ||
objects (a variant of a builder-style API), which allows configuration | ||
to be done independently of the blocking operation being configured. | ||
|
||
Unfortunately, as explained [above](#timeouts), this stateful approach | ||
has poor composability, since users of an IO objects can accidentally | ||
interfere with one another. | ||
|
||
The proposed solution is to instead offer a `with_deadline` method | ||
(correcting the terminology) that, rather than changing the state of | ||
an object, creates a *wrapper* object with the given deadline. | ||
|
||
```rust | ||
struct Deadline { | ||
... // to be determined | ||
} | ||
|
||
trait IntoDeadine { | ||
fn into_deadline(self) -> Deadline; | ||
} | ||
|
||
struct Deadlined<T> { | ||
deadline: Deadline, | ||
inner: T, | ||
} | ||
|
||
impl<T> Deadlined<T> { | ||
pub fn new<D: IntoDeadline>(inner: T, deadline: D) -> Deadlined<T> { | ||
Deadlined { deadline: deadline, inner: inner } | ||
} | ||
|
||
pub fn deadline(&self) -> Deadline { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh, implement |
||
self.deadline | ||
} | ||
|
||
pub fn inner(&self) -> &T { | ||
&self.inner | ||
} | ||
|
||
pub fn inner_mut(&mut self) -> &mut T { | ||
&mut self.inner | ||
} | ||
|
||
pub fn into_inner(self) -> T { | ||
self.inner | ||
} | ||
} | ||
|
||
impl TcpStream { | ||
fn with_deadline<D>(&mut self, deadline: D) -> Deadlined<&mut TcpStream> where | ||
D: IntoDeadline | ||
{ | ||
Deadlined::new(self, deadline) | ||
} | ||
} | ||
|
||
impl<'a> Reader for Deadlined<&'a mut TcpStream> { | ||
type Err = IoError; | ||
fn read(&mut self, buf: &mut [u8]) -> Result<uint, Err> { | ||
// read, using the specified deadline | ||
} | ||
} | ||
|
||
// And so on for other traits and concrete types | ||
``` | ||
|
||
The exact details of `Deadline` and the `impl`s for `IntoDeadline` are | ||
left unspecified, as they will depend on what notions of time are | ||
available in `std`, but they will at least include a way to specify an | ||
absolute time. | ||
|
||
### Timeouts versus deadlines | ||
[Timeouts versus deadlines]: #timeouts-versus-deadlines | ||
|
||
This RFC is not going to delve deeply into the timeout versus deadline | ||
debate, but the main motivation for using deadlines is for *compound* | ||
operations like `write_all`. With a deadline-based approach, it's | ||
possible to bound the total amount of time taken even though an | ||
operation involves many system calls. Doing so with timeouts is | ||
harder, since the timeout must change as the operations progress | ||
(requiring re-checking the clock each time). | ||
|
||
## Splitting streams and cancellation | ||
[Splitting streams and cancellation]: #splitting-streams-and-cancellation | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rust's