banner
amtoaer

晓风残月

叹息似的渺茫,你仍要保存着那真!
github
telegram
email
x
bilibili
steam
nintendo switch

Differences between the flush method in tokio::fs and the method with the same name in the standard library

When performing file read and write operations in the Tokio asynchronous context, a commonly used module is tokio::fs, which contains the asynchronous version of the standard library file API with the same name.

Most file methods have the same semantics as the methods in the standard library, but the flush method is slightly different.

Starting from the tokio::fs documentation#

As of writing this article, the latest version of Tokio is 1.43.0. Clicking on the documentation link provides a brief introduction to the module:

image

According to the documentation, since most operating systems do not provide asynchronous file system APIs, the asynchronous file operations of tokio::fs actually execute general synchronous file operations in the spawn_blocking thread pool.

In the future, it may switch to asynchronous file system APIs like io_uring, but at least currently, it is implemented using a thread pool on all platforms.

Special note on the flush method in the documentation#

Scrolling down a bit, we can see the following description:

image

image

The documentation specifically uses Note to remind users that it is important to use flush when writing to a Tokio File, because calls to the write method will return before the write is complete, and flush must be explicitly called to wait for the write to finish.

This is different from the standard library's File, which is caused by the underlying implementation of spawn_blocking.

Standard library's flush#

Why does Tokio need to remind users to call flush? Is there no flush in the standard library or is it unnecessary to call flush? This requires looking back at the standard library documentation.

image

Indeed! Since the File structure does not contain a buffer, the flush method on Unix and Windows does not perform any operations. In other words, forgetting to flush when writing with the standard library's File will not affect any program logic on 99.99% of platforms.

image

Of course, the documentation also adds that this is just a lower-level explanation to aid understanding and is not binding; the behavior in subsequent versions may also change.

Additional explanation#

During my research, I found a reply from alice, a main author of Tokio, in the forum, which may help with understanding.

A completed write on a tokio::fs::File means that it has been handed off to the threadpool to be written, but that does not necessarily mean that the threadpool has written it yet. Calling flush allows you to wait for that to happen.

It's not possible to change this. The AsyncWrite trait's signature fundamentally forces us to do it this way.

A completed write operation on tokio::fs::File means it has been handed off to the thread pool for writing, but this does not necessarily mean that the thread pool has completed the write. Calling flush allows you to wait for the write operation to actually finish.

This cannot be changed. The signature of the AsyncWrite trait fundamentally forces us to handle it this way.

Conclusion#

Putting aside the details, we can draw a simple conclusion:

Not calling flush after writing to a file may lead to errors, but calling flush definitely won't!

Flushing the buffer after writing a file is a good habit; it may not have an effect, but it certainly won't cause any problems. 😋

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.