Skip to content
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

AsyncSeek #9

Open
nrc opened this issue Mar 21, 2022 · 5 comments
Open

AsyncSeek #9

nrc opened this issue Mar 21, 2022 · 5 comments
Labels
A-stdlib Area: a standard library for async Rust

Comments

@nrc
Copy link
Owner

nrc commented Mar 21, 2022

An async version of the Seek trait:

pub trait Seek {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64>;

    fn rewind(&mut self) -> Result<()> { ... }
    fn stream_len(&mut self) -> Result<u64> { ... }
    fn stream_position(&mut self) -> Result<u64> { ... }
}

Prior art

futures-rs

pub trait AsyncSeek {
    fn poll_seek(
        self: Pin<&mut Self>, 
        cx: &mut Context<'_>, 
        pos: SeekFrom
    ) -> Poll<Result<u64>>;
}

Tokio

pub trait AsyncSeek {
    fn start_seek(self: Pin<&mut Self>, position: SeekFrom) -> Result<()>;

    fn poll_complete(
        self: Pin<&mut Self>, 
        cx: &mut Context<'_>
    ) -> Poll<Result<u64>>;
}

async-std

Extends futures-rs with a convenience seek function

    fn seek(&mut self, pos: SeekFrom) -> ImplFuture<Result<u64>>
    where
        Self: Unpin,
    { ... }

Misc

@nrc nrc added the A-stdlib Area: a standard library for async Rust label Mar 21, 2022
@nrc
Copy link
Owner Author

nrc commented Mar 21, 2022

An obvious async-ing of the sync version gives:

pub trait Seek {
    async fn seek(&mut self, pos: SeekFrom) -> Result<u64>;

    async fn rewind(&mut self) -> Result<()> { ... }
    async fn stream_len(&mut self) -> Result<u64> { ... }
    async fn stream_position(&mut self) -> Result<u64> { ... }
}

Everything must be async since the underlying reader might need to read data to fulfil the seek requests.

@nrc
Copy link
Owner Author

nrc commented Mar 21, 2022

I think it would be easy enough to extend the readiness proposal for read/write to seek. (We'd add a SEEK interest and the async::Seek trait would extend Ready. seek would be a provided method and we'd add a non_blocking_seek required method). I don't think that is super useful though. Seek only makes sense on buffered IO or files and in either case I don't think we have memory requirements that Read has.

@nrc
Copy link
Owner Author

nrc commented Mar 21, 2022

Note that although we should have Seek for symmetry with sync IO, a read_at/write_at API might make more sense for many users. I'm not sure if we should think about that API now or later, or if one should be implemented in terms of the other.

@nrc
Copy link
Owner Author

nrc commented Mar 23, 2022

Some issue spelunking around the Tokio design:

To summarise the concern with poll_seek, the scenario is that someone calls the function (possibly a few times) but then stops (i.e., cancels the seek). What should be the effect on the file? And what guarantees can the seek function make about the state of the file. Phrased differently, it is common to expect that a future returning NotReady does not have any side-effects, but a straightforward implementation does not have that property. Splitting the function gets around this question, if a user calls start_seek, they can expect the seek to (probably) happen at some point in the future. seek_complete then just checks whether the seek has happened, and is thus side effect-free in the NotReady case.

I think there are slightly different expectations around async functions, though we must still consider cancellation. I think that as long as an async function is awaited then the user can expect side-effects and there is no expectation of side-effect-free-ness in the event of cancellation, e.g., consider an async read under a completion IO model. So I think that if we get a better story around cancellation then we might be able to do better, but for now, a simple async fn seek seems fine.

@Xuanwo
Copy link

Xuanwo commented Jul 28, 2022

I found rewind, stream_len and stream_position are not very useful. For the std version, they are often treated as different alternatives to SeekFrom. Do we have scenarios for those APIs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-stdlib Area: a standard library for async Rust
Projects
None yet
Development

No branches or pull requests

2 participants