Skip to main content

tokio/io/util/
mem.rs

1//! In-process memory IO types.
2
3use crate::io::{split, AsyncRead, AsyncWrite, ReadBuf, ReadHalf, WriteHalf};
4use crate::loom::sync::Mutex;
5
6use bytes::{Buf, BytesMut};
7use std::{
8    pin::Pin,
9    sync::Arc,
10    task::{self, ready, Poll, Waker},
11};
12
13/// A bidirectional pipe to read and write bytes in memory.
14///
15/// A pair of `DuplexStream`s are created together, and they act as a "channel"
16/// that can be used as in-memory IO types. Writing to one of the pairs will
17/// allow that data to be read from the other, and vice versa.
18///
19/// # Closing a `DuplexStream`
20///
21/// If one end of the `DuplexStream` channel is dropped, any pending reads on
22/// the other side will continue to read data until the buffer is drained, then
23/// they will signal EOF by returning 0 bytes. Any writes to the other side,
24/// including pending ones (that are waiting for free space in the buffer) will
25/// return `Err(BrokenPipe)` immediately.
26///
27/// # Example
28///
29/// ```
30/// # async fn ex() -> std::io::Result<()> {
31/// # use tokio::io::{AsyncReadExt, AsyncWriteExt};
32/// let (mut client, mut server) = tokio::io::duplex(64);
33///
34/// client.write_all(b"ping").await?;
35///
36/// let mut buf = [0u8; 4];
37/// server.read_exact(&mut buf).await?;
38/// assert_eq!(&buf, b"ping");
39///
40/// server.write_all(b"pong").await?;
41///
42/// client.read_exact(&mut buf).await?;
43/// assert_eq!(&buf, b"pong");
44/// # Ok(())
45/// # }
46/// ```
47#[derive(Debug)]
48#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
49pub struct DuplexStream {
50    read: Arc<Mutex<SimplexStream>>,
51    write: Arc<Mutex<SimplexStream>>,
52}
53
54/// A unidirectional pipe to read and write bytes in memory.
55///
56/// It can be constructed by [`simplex`] function which will create a pair of
57/// reader and writer or by calling [`SimplexStream::new_unsplit`] that will
58/// create a handle for both reading and writing.
59///
60/// # Example
61///
62/// ```
63/// # async fn ex() -> std::io::Result<()> {
64/// # use tokio::io::{AsyncReadExt, AsyncWriteExt};
65/// let (mut receiver, mut sender) = tokio::io::simplex(64);
66///
67/// sender.write_all(b"ping").await?;
68///
69/// let mut buf = [0u8; 4];
70/// receiver.read_exact(&mut buf).await?;
71/// assert_eq!(&buf, b"ping");
72/// # Ok(())
73/// # }
74/// ```
75#[derive(Debug)]
76#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
77pub struct SimplexStream {
78    /// The buffer storing the bytes written, also read from.
79    ///
80    /// Using a `BytesMut` because it has efficient `Buf` and `BufMut`
81    /// functionality already. Additionally, it can try to copy data in the
82    /// same buffer if there read index has advanced far enough.
83    buffer: BytesMut,
84    /// Determines if the write side has been closed.
85    is_closed: bool,
86    /// The maximum amount of bytes that can be written before returning
87    /// `Poll::Pending`.
88    max_buf_size: usize,
89    /// If the `read` side has been polled and is pending, this is the waker
90    /// for that parked task.
91    read_waker: Option<Waker>,
92    /// If the `write` side has filled the `max_buf_size` and returned
93    /// `Poll::Pending`, this is the waker for that parked task.
94    write_waker: Option<Waker>,
95}
96
97// ===== impl DuplexStream =====
98
99/// Create a new pair of `DuplexStream`s that act like a pair of connected sockets.
100///
101/// The `max_buf_size` argument is the maximum amount of bytes that can be
102/// written to a side before the write returns `Poll::Pending`.
103#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
104pub fn duplex(max_buf_size: usize) -> (DuplexStream, DuplexStream) {
105    let one = Arc::new(Mutex::new(SimplexStream::new_unsplit(max_buf_size)));
106    let two = Arc::new(Mutex::new(SimplexStream::new_unsplit(max_buf_size)));
107
108    (
109        DuplexStream {
110            read: one.clone(),
111            write: two.clone(),
112        },
113        DuplexStream {
114            read: two,
115            write: one,
116        },
117    )
118}
119
120impl AsyncRead for DuplexStream {
121    // Previous rustc required this `self` to be `mut`, even though newer
122    // versions recognize it isn't needed to call `lock()`. So for
123    // compatibility, we include the `mut` and `allow` the lint.
124    //
125    // See https://github.com/rust-lang/rust/issues/73592
126    #[allow(unused_mut)]
127    fn poll_read(
128        mut self: Pin<&mut Self>,
129        cx: &mut task::Context<'_>,
130        buf: &mut ReadBuf<'_>,
131    ) -> Poll<std::io::Result<()>> {
132        let mut wakers = Wakers::default();
133        let ret = Pin::new(&mut *self.read.lock()).poll_read_deferred(cx, buf, &mut wakers);
134        wakers.wake();
135        ret
136    }
137}
138
139impl AsyncWrite for DuplexStream {
140    #[allow(unused_mut)]
141    fn poll_write(
142        mut self: Pin<&mut Self>,
143        cx: &mut task::Context<'_>,
144        buf: &[u8],
145    ) -> Poll<std::io::Result<usize>> {
146        let mut wakers = Wakers::default();
147        let ret = Pin::new(&mut *self.write.lock()).poll_write_deferred(cx, buf, &mut wakers);
148        wakers.wake();
149        ret
150    }
151
152    fn poll_write_vectored(
153        self: Pin<&mut Self>,
154        cx: &mut task::Context<'_>,
155        bufs: &[std::io::IoSlice<'_>],
156    ) -> Poll<Result<usize, std::io::Error>> {
157        let mut wakers = Wakers::default();
158        let ret =
159            Pin::new(&mut *self.write.lock()).poll_write_vectored_deferred(cx, bufs, &mut wakers);
160        wakers.wake();
161        ret
162    }
163
164    fn is_write_vectored(&self) -> bool {
165        true
166    }
167
168    #[allow(unused_mut)]
169    fn poll_flush(
170        mut self: Pin<&mut Self>,
171        cx: &mut task::Context<'_>,
172    ) -> Poll<std::io::Result<()>> {
173        Pin::new(&mut *self.write.lock()).poll_flush(cx)
174    }
175
176    #[allow(unused_mut)]
177    fn poll_shutdown(
178        mut self: Pin<&mut Self>,
179        _: &mut task::Context<'_>,
180    ) -> Poll<std::io::Result<()>> {
181        let read_waker = self.write.lock().close_write();
182        if let Some(waker) = read_waker {
183            waker.wake();
184        }
185        Poll::Ready(Ok(()))
186    }
187}
188
189impl Drop for DuplexStream {
190    fn drop(&mut self) {
191        // notify the other side of the closure
192        let read_waker = self.write.lock().close_write();
193        let write_waker = self.read.lock().close_read();
194        // wake after releasing the locks, as the wakers may access the pipe
195        if let Some(waker) = read_waker {
196            waker.wake();
197        }
198        if let Some(waker) = write_waker {
199            waker.wake();
200        }
201    }
202}
203
204/// Wakers taken out of a `SimplexStream` by a read or write.
205///
206/// A `DuplexStream` keeps its `SimplexStream`s behind a mutex, and wakes and
207/// drops these wakers only after releasing it, as they may access the pipe.
208/// The halves returned by `simplex()` are still polled under the mutex in
209/// `split`.
210#[derive(Default)]
211struct Wakers {
212    /// The waker of the other side of the pipe, which needs to be woken.
213    wake: Option<Waker>,
214    /// The previously registered waker, which was replaced by a new one.
215    replaced: Option<Waker>,
216}
217
218impl Wakers {
219    fn wake(self) {
220        if let Some(waker) = self.wake {
221            waker.wake();
222        }
223        drop(self.replaced);
224    }
225}
226
227// ===== impl SimplexStream =====
228
229/// Creates unidirectional buffer that acts like in memory pipe.
230///
231/// The `max_buf_size` argument is the maximum amount of bytes that can be
232/// written to a buffer before it returns `Poll::Pending`.
233///
234/// # Unify reader and writer
235///
236/// The reader and writer half can be unified into a single structure
237/// of `SimplexStream` that supports both reading and writing or
238/// the `SimplexStream` can be already created as unified structure
239/// using [`SimplexStream::new_unsplit()`].
240///
241/// ```
242/// # async fn ex() -> std::io::Result<()> {
243/// # use tokio::io::{AsyncReadExt, AsyncWriteExt};
244/// let (reader, writer) = tokio::io::simplex(64);
245/// let mut simplex_stream = reader.unsplit(writer);
246/// simplex_stream.write_all(b"hello").await?;
247///
248/// let mut buf = [0u8; 5];
249/// simplex_stream.read_exact(&mut buf).await?;
250/// assert_eq!(&buf, b"hello");
251/// # Ok(())
252/// # }
253/// ```
254#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
255pub fn simplex(max_buf_size: usize) -> (ReadHalf<SimplexStream>, WriteHalf<SimplexStream>) {
256    split(SimplexStream::new_unsplit(max_buf_size))
257}
258
259impl SimplexStream {
260    /// Creates unidirectional buffer that acts like in memory pipe. To create split
261    /// version with separate reader and writer you can use [`simplex`] function.
262    ///
263    /// The `max_buf_size` argument is the maximum amount of bytes that can be
264    /// written to a buffer before it returns `Poll::Pending`.
265    #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
266    pub fn new_unsplit(max_buf_size: usize) -> SimplexStream {
267        SimplexStream {
268            buffer: BytesMut::new(),
269            is_closed: false,
270            max_buf_size,
271            read_waker: None,
272            write_waker: None,
273        }
274    }
275
276    /// Closes the pipe and returns the reader's waker, which needs to be woken
277    /// so it learns that no more data will come.
278    #[must_use]
279    fn close_write(&mut self) -> Option<Waker> {
280        self.is_closed = true;
281        self.read_waker.take()
282    }
283
284    /// Closes the pipe and returns the writer's waker, which needs to be woken
285    /// so it learns that it has to abort.
286    #[must_use]
287    fn close_read(&mut self) -> Option<Waker> {
288        self.is_closed = true;
289        self.write_waker.take()
290    }
291
292    fn poll_read_internal(
293        mut self: Pin<&mut Self>,
294        cx: &mut task::Context<'_>,
295        buf: &mut ReadBuf<'_>,
296        wakers: &mut Wakers,
297    ) -> Poll<std::io::Result<()>> {
298        if self.buffer.has_remaining() {
299            let max = self.buffer.remaining().min(buf.remaining());
300            buf.put_slice(&self.buffer[..max]);
301            self.buffer.advance(max);
302            if max > 0 {
303                // The passed `buf` might have been empty, don't wake up if
304                // no bytes have been moved.
305                wakers.wake = self.write_waker.take();
306            }
307            Poll::Ready(Ok(()))
308        } else if self.is_closed {
309            Poll::Ready(Ok(()))
310        } else {
311            wakers.replaced = self.read_waker.replace(cx.waker().clone());
312            Poll::Pending
313        }
314    }
315
316    fn poll_write_internal(
317        mut self: Pin<&mut Self>,
318        cx: &mut task::Context<'_>,
319        buf: &[u8],
320        wakers: &mut Wakers,
321    ) -> Poll<std::io::Result<usize>> {
322        if self.is_closed {
323            return Poll::Ready(Err(std::io::ErrorKind::BrokenPipe.into()));
324        }
325        let avail = self.max_buf_size - self.buffer.len();
326        if avail == 0 {
327            wakers.replaced = self.write_waker.replace(cx.waker().clone());
328            return Poll::Pending;
329        }
330
331        let len = buf.len().min(avail);
332        self.buffer.extend_from_slice(&buf[..len]);
333        wakers.wake = self.read_waker.take();
334        Poll::Ready(Ok(len))
335    }
336
337    fn poll_write_vectored_internal(
338        mut self: Pin<&mut Self>,
339        cx: &mut task::Context<'_>,
340        bufs: &[std::io::IoSlice<'_>],
341        wakers: &mut Wakers,
342    ) -> Poll<Result<usize, std::io::Error>> {
343        if self.is_closed {
344            return Poll::Ready(Err(std::io::ErrorKind::BrokenPipe.into()));
345        }
346        let avail = self.max_buf_size - self.buffer.len();
347        if avail == 0 {
348            wakers.replaced = self.write_waker.replace(cx.waker().clone());
349            return Poll::Pending;
350        }
351
352        let mut rem = avail;
353        for buf in bufs {
354            if rem == 0 {
355                break;
356            }
357
358            let len = buf.len().min(rem);
359            self.buffer.extend_from_slice(&buf[..len]);
360            rem -= len;
361        }
362
363        wakers.wake = self.read_waker.take();
364        Poll::Ready(Ok(avail - rem))
365    }
366
367    cfg_coop! {
368        fn poll_read_deferred(
369            self: Pin<&mut Self>,
370            cx: &mut task::Context<'_>,
371            buf: &mut ReadBuf<'_>,
372            wakers: &mut Wakers,
373        ) -> Poll<std::io::Result<()>> {
374            ready!(crate::trace::trace_leaf(cx));
375            let coop = ready!(crate::task::coop::poll_proceed(cx));
376
377            let ret = self.poll_read_internal(cx, buf, wakers);
378            if ret.is_ready() {
379                coop.made_progress();
380            }
381            ret
382        }
383    }
384
385    cfg_not_coop! {
386        fn poll_read_deferred(
387            self: Pin<&mut Self>,
388            cx: &mut task::Context<'_>,
389            buf: &mut ReadBuf<'_>,
390            wakers: &mut Wakers,
391        ) -> Poll<std::io::Result<()>> {
392            ready!(crate::trace::trace_leaf(cx));
393            self.poll_read_internal(cx, buf, wakers)
394        }
395    }
396
397    cfg_coop! {
398        fn poll_write_deferred(
399            self: Pin<&mut Self>,
400            cx: &mut task::Context<'_>,
401            buf: &[u8],
402            wakers: &mut Wakers,
403        ) -> Poll<std::io::Result<usize>> {
404            ready!(crate::trace::trace_leaf(cx));
405            let coop = ready!(crate::task::coop::poll_proceed(cx));
406
407            let ret = self.poll_write_internal(cx, buf, wakers);
408            if ret.is_ready() {
409                coop.made_progress();
410            }
411            ret
412        }
413    }
414
415    cfg_not_coop! {
416        fn poll_write_deferred(
417            self: Pin<&mut Self>,
418            cx: &mut task::Context<'_>,
419            buf: &[u8],
420            wakers: &mut Wakers,
421        ) -> Poll<std::io::Result<usize>> {
422            ready!(crate::trace::trace_leaf(cx));
423            self.poll_write_internal(cx, buf, wakers)
424        }
425    }
426
427    cfg_coop! {
428        fn poll_write_vectored_deferred(
429            self: Pin<&mut Self>,
430            cx: &mut task::Context<'_>,
431            bufs: &[std::io::IoSlice<'_>],
432            wakers: &mut Wakers,
433        ) -> Poll<Result<usize, std::io::Error>> {
434            ready!(crate::trace::trace_leaf(cx));
435            let coop = ready!(crate::task::coop::poll_proceed(cx));
436
437            let ret = self.poll_write_vectored_internal(cx, bufs, wakers);
438            if ret.is_ready() {
439                coop.made_progress();
440            }
441            ret
442        }
443    }
444
445    cfg_not_coop! {
446        fn poll_write_vectored_deferred(
447            self: Pin<&mut Self>,
448            cx: &mut task::Context<'_>,
449            bufs: &[std::io::IoSlice<'_>],
450            wakers: &mut Wakers,
451        ) -> Poll<Result<usize, std::io::Error>> {
452            ready!(crate::trace::trace_leaf(cx));
453            self.poll_write_vectored_internal(cx, bufs, wakers)
454        }
455    }
456}
457
458impl AsyncRead for SimplexStream {
459    fn poll_read(
460        self: Pin<&mut Self>,
461        cx: &mut task::Context<'_>,
462        buf: &mut ReadBuf<'_>,
463    ) -> Poll<std::io::Result<()>> {
464        let mut wakers = Wakers::default();
465        let ret = self.poll_read_deferred(cx, buf, &mut wakers);
466        wakers.wake();
467        ret
468    }
469}
470
471impl AsyncWrite for SimplexStream {
472    fn poll_write(
473        self: Pin<&mut Self>,
474        cx: &mut task::Context<'_>,
475        buf: &[u8],
476    ) -> Poll<std::io::Result<usize>> {
477        let mut wakers = Wakers::default();
478        let ret = self.poll_write_deferred(cx, buf, &mut wakers);
479        wakers.wake();
480        ret
481    }
482
483    fn poll_write_vectored(
484        self: Pin<&mut Self>,
485        cx: &mut task::Context<'_>,
486        bufs: &[std::io::IoSlice<'_>],
487    ) -> Poll<Result<usize, std::io::Error>> {
488        let mut wakers = Wakers::default();
489        let ret = self.poll_write_vectored_deferred(cx, bufs, &mut wakers);
490        wakers.wake();
491        ret
492    }
493
494    fn is_write_vectored(&self) -> bool {
495        true
496    }
497
498    fn poll_flush(self: Pin<&mut Self>, _: &mut task::Context<'_>) -> Poll<std::io::Result<()>> {
499        Poll::Ready(Ok(()))
500    }
501
502    fn poll_shutdown(
503        mut self: Pin<&mut Self>,
504        _: &mut task::Context<'_>,
505    ) -> Poll<std::io::Result<()>> {
506        if let Some(waker) = self.close_write() {
507            waker.wake();
508        }
509        Poll::Ready(Ok(()))
510    }
511}