Minor terminology fix: we don't have any classes. It's just types, or struct/enum when it's more appropriate. For me it was crucial to use the term "class" to understand the Rust better.
tl;dr: No you don't have to, it's just more convenient.
Checkout the signature of the methods of the
AsyncWrite traits. They have
poll_* methods which checks readiness of the IO operation, without blocking the thread. It's possible to implement
std::future::Future manually on your custom type which read/write concurrently without split it. But to do so you need to understand how exactly the Rust's async system works, sometimes requires deep understanding of the underlying executors and the pinning semantics. And there's no guarantee that the result of such efforts would outperforms the solution with
You certainly can, in fact the generic
tokio::io::split function does exactly that by wrapping the given resource in an
Arc<Mutex<...>> and having polls on each half call the two kinds of polls in an interleaved manner.
However, the generic version must use a Mutex. Why? The poll functions take
&mut self, so you must have exclusive access to poll the io resource in either way.
On the other hand, the dedicated split and into_split functions on
TcpStream do not use a Mutex, because they have the special knowledge that they are talking to a tcp stream, and your OS has no issue with parallel reading and writing. The generic one cannot do this, since the type might not have that capability.
tokio::io::split exist? Some work flows are much easier to write when you can split it.
Arc<TcpStream>) not implement
AsyncRead + AsyncWrite? Because although Tokio supports both reads and writes in parallel, we don't support two parallel reads, or two parallel writes, which splitting still doesn't allow.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.