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///
104/// # Panics
105///
106/// This function panics if `max_buf_size` is 0.
107#[track_caller]
108#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
109pub fn duplex(max_buf_size: usize) -> (DuplexStream, DuplexStream) {
110    let one = Arc::new(Mutex::new(SimplexStream::new_unsplit(max_buf_size)));
111    let two = Arc::new(Mutex::new(SimplexStream::new_unsplit(max_buf_size)));
112
113    (
114        DuplexStream {
115            read: one.clone(),
116            write: two.clone(),
117        },
118        DuplexStream {
119            read: two,
120            write: one,
121        },
122    )
123}
124
125impl AsyncRead for DuplexStream {
126    // Previous rustc required this `self` to be `mut`, even though newer
127    // versions recognize it isn't needed to call `lock()`. So for
128    // compatibility, we include the `mut` and `allow` the lint.
129    //
130    // See https://github.com/rust-lang/rust/issues/73592
131    #[allow(unused_mut)]
132    fn poll_read(
133        mut self: Pin<&mut Self>,
134        cx: &mut task::Context<'_>,
135        buf: &mut ReadBuf<'_>,
136    ) -> Poll<std::io::Result<()>> {
137        let mut wakers = Wakers::default();
138        let ret = Pin::new(&mut *self.read.lock()).poll_read_deferred(cx, buf, &mut wakers);
139        wakers.wake();
140        ret
141    }
142}
143
144impl AsyncWrite for DuplexStream {
145    #[allow(unused_mut)]
146    fn poll_write(
147        mut self: Pin<&mut Self>,
148        cx: &mut task::Context<'_>,
149        buf: &[u8],
150    ) -> Poll<std::io::Result<usize>> {
151        let mut wakers = Wakers::default();
152        let ret = Pin::new(&mut *self.write.lock()).poll_write_deferred(cx, buf, &mut wakers);
153        wakers.wake();
154        ret
155    }
156
157    fn poll_write_vectored(
158        self: Pin<&mut Self>,
159        cx: &mut task::Context<'_>,
160        bufs: &[std::io::IoSlice<'_>],
161    ) -> Poll<Result<usize, std::io::Error>> {
162        let mut wakers = Wakers::default();
163        let ret =
164            Pin::new(&mut *self.write.lock()).poll_write_vectored_deferred(cx, bufs, &mut wakers);
165        wakers.wake();
166        ret
167    }
168
169    fn is_write_vectored(&self) -> bool {
170        true
171    }
172
173    #[allow(unused_mut)]
174    fn poll_flush(
175        mut self: Pin<&mut Self>,
176        cx: &mut task::Context<'_>,
177    ) -> Poll<std::io::Result<()>> {
178        Pin::new(&mut *self.write.lock()).poll_flush(cx)
179    }
180
181    #[allow(unused_mut)]
182    fn poll_shutdown(
183        mut self: Pin<&mut Self>,
184        _: &mut task::Context<'_>,
185    ) -> Poll<std::io::Result<()>> {
186        let read_waker = self.write.lock().close_write();
187        if let Some(waker) = read_waker {
188            waker.wake();
189        }
190        Poll::Ready(Ok(()))
191    }
192}
193
194impl Drop for DuplexStream {
195    fn drop(&mut self) {
196        // notify the other side of the closure
197        let read_waker = self.write.lock().close_write();
198        let write_waker = self.read.lock().close_read();
199        // wake after releasing the locks, as the wakers may access the pipe
200        if let Some(waker) = read_waker {
201            waker.wake();
202        }
203        if let Some(waker) = write_waker {
204            waker.wake();
205        }
206    }
207}
208
209/// Wakers taken out of a `SimplexStream` by a read or write.
210///
211/// A `DuplexStream` keeps its `SimplexStream`s behind a mutex, and wakes and
212/// drops these wakers only after releasing it, as they may access the pipe.
213/// The halves returned by `simplex()` are still polled under the mutex in
214/// `split`.
215#[derive(Default)]
216struct Wakers {
217    /// The waker of the other side of the pipe, which needs to be woken.
218    wake: Option<Waker>,
219    /// The previously registered waker, which was replaced by a new one.
220    replaced: Option<Waker>,
221}
222
223impl Wakers {
224    fn wake(self) {
225        if let Some(waker) = self.wake {
226            waker.wake();
227        }
228        drop(self.replaced);
229    }
230}
231
232// ===== impl SimplexStream =====
233
234/// Creates unidirectional buffer that acts like in memory pipe.
235///
236/// The `max_buf_size` argument is the maximum amount of bytes that can be
237/// written to a buffer before it returns `Poll::Pending`.
238///
239/// # Unify reader and writer
240///
241/// The reader and writer half can be unified into a single structure
242/// of `SimplexStream` that supports both reading and writing or
243/// the `SimplexStream` can be already created as unified structure
244/// using [`SimplexStream::new_unsplit()`].
245///
246/// ```
247/// # async fn ex() -> std::io::Result<()> {
248/// # use tokio::io::{AsyncReadExt, AsyncWriteExt};
249/// let (reader, writer) = tokio::io::simplex(64);
250/// let mut simplex_stream = reader.unsplit(writer);
251/// simplex_stream.write_all(b"hello").await?;
252///
253/// let mut buf = [0u8; 5];
254/// simplex_stream.read_exact(&mut buf).await?;
255/// assert_eq!(&buf, b"hello");
256/// # Ok(())
257/// # }
258/// ```
259///
260/// # Panics
261///
262/// This function panics if `max_buf_size` is 0.
263#[track_caller]
264#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
265pub fn simplex(max_buf_size: usize) -> (ReadHalf<SimplexStream>, WriteHalf<SimplexStream>) {
266    split(SimplexStream::new_unsplit(max_buf_size))
267}
268
269impl SimplexStream {
270    /// Creates unidirectional buffer that acts like in memory pipe. To create split
271    /// version with separate reader and writer you can use [`simplex`] function.
272    ///
273    /// The `max_buf_size` argument is the maximum amount of bytes that can be
274    /// written to a buffer before it returns `Poll::Pending`.
275    ///
276    /// # Panics
277    ///
278    /// This function panics if `max_buf_size` is 0.
279    #[track_caller]
280    #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
281    pub fn new_unsplit(max_buf_size: usize) -> SimplexStream {
282        assert!(max_buf_size > 0, "`max_buf_size` must be greater than 0");
283        SimplexStream {
284            buffer: BytesMut::new(),
285            is_closed: false,
286            max_buf_size,
287            read_waker: None,
288            write_waker: None,
289        }
290    }
291
292    /// Closes the pipe and returns the reader's waker, which needs to be woken
293    /// so it learns that no more data will come.
294    #[must_use]
295    fn close_write(&mut self) -> Option<Waker> {
296        self.is_closed = true;
297        self.read_waker.take()
298    }
299
300    /// Closes the pipe and returns the writer's waker, which needs to be woken
301    /// so it learns that it has to abort.
302    #[must_use]
303    fn close_read(&mut self) -> Option<Waker> {
304        self.is_closed = true;
305        self.write_waker.take()
306    }
307
308    fn poll_read_internal(
309        mut self: Pin<&mut Self>,
310        cx: &mut task::Context<'_>,
311        buf: &mut ReadBuf<'_>,
312        wakers: &mut Wakers,
313    ) -> Poll<std::io::Result<()>> {
314        if buf.remaining() == 0 {
315            return Poll::Ready(Ok(()));
316        }
317
318        if self.buffer.has_remaining() {
319            let max = self.buffer.remaining().min(buf.remaining());
320            buf.put_slice(&self.buffer[..max]);
321            self.buffer.advance(max);
322            if max > 0 {
323                // The passed `buf` might have been empty, don't wake up if
324                // no bytes have been moved.
325                wakers.wake = self.write_waker.take();
326            }
327            Poll::Ready(Ok(()))
328        } else if self.is_closed {
329            Poll::Ready(Ok(()))
330        } else {
331            wakers.replaced = self.read_waker.replace(cx.waker().clone());
332            Poll::Pending
333        }
334    }
335
336    fn poll_write_internal(
337        mut self: Pin<&mut Self>,
338        cx: &mut task::Context<'_>,
339        buf: &[u8],
340        wakers: &mut Wakers,
341    ) -> Poll<std::io::Result<usize>> {
342        if self.is_closed {
343            return Poll::Ready(Err(std::io::ErrorKind::BrokenPipe.into()));
344        }
345        if buf.is_empty() {
346            return Poll::Ready(Ok(0));
347        }
348
349        let avail = self.max_buf_size - self.buffer.len();
350        if avail == 0 {
351            wakers.replaced = self.write_waker.replace(cx.waker().clone());
352            return Poll::Pending;
353        }
354
355        let len = buf.len().min(avail);
356        self.buffer.extend_from_slice(&buf[..len]);
357        wakers.wake = self.read_waker.take();
358        Poll::Ready(Ok(len))
359    }
360
361    fn poll_write_vectored_internal(
362        mut self: Pin<&mut Self>,
363        cx: &mut task::Context<'_>,
364        bufs: &[std::io::IoSlice<'_>],
365        wakers: &mut Wakers,
366    ) -> Poll<Result<usize, std::io::Error>> {
367        if self.is_closed {
368            return Poll::Ready(Err(std::io::ErrorKind::BrokenPipe.into()));
369        }
370        if bufs.iter().all(|buf| buf.is_empty()) {
371            return Poll::Ready(Ok(0));
372        }
373
374        let avail = self.max_buf_size - self.buffer.len();
375        if avail == 0 {
376            wakers.replaced = self.write_waker.replace(cx.waker().clone());
377            return Poll::Pending;
378        }
379
380        let mut rem = avail;
381        for buf in bufs {
382            if rem == 0 {
383                break;
384            }
385
386            let len = buf.len().min(rem);
387            self.buffer.extend_from_slice(&buf[..len]);
388            rem -= len;
389        }
390
391        wakers.wake = self.read_waker.take();
392        Poll::Ready(Ok(avail - rem))
393    }
394
395    cfg_coop! {
396        fn poll_read_deferred(
397            self: Pin<&mut Self>,
398            cx: &mut task::Context<'_>,
399            buf: &mut ReadBuf<'_>,
400            wakers: &mut Wakers,
401        ) -> Poll<std::io::Result<()>> {
402            ready!(crate::trace::trace_leaf(cx));
403            let coop = ready!(crate::task::coop::poll_proceed(cx));
404
405            let ret = self.poll_read_internal(cx, buf, wakers);
406            if ret.is_ready() {
407                coop.made_progress();
408            }
409            ret
410        }
411    }
412
413    cfg_not_coop! {
414        fn poll_read_deferred(
415            self: Pin<&mut Self>,
416            cx: &mut task::Context<'_>,
417            buf: &mut ReadBuf<'_>,
418            wakers: &mut Wakers,
419        ) -> Poll<std::io::Result<()>> {
420            ready!(crate::trace::trace_leaf(cx));
421            self.poll_read_internal(cx, buf, wakers)
422        }
423    }
424
425    cfg_coop! {
426        fn poll_write_deferred(
427            self: Pin<&mut Self>,
428            cx: &mut task::Context<'_>,
429            buf: &[u8],
430            wakers: &mut Wakers,
431        ) -> Poll<std::io::Result<usize>> {
432            ready!(crate::trace::trace_leaf(cx));
433            let coop = ready!(crate::task::coop::poll_proceed(cx));
434
435            let ret = self.poll_write_internal(cx, buf, wakers);
436            if ret.is_ready() {
437                coop.made_progress();
438            }
439            ret
440        }
441    }
442
443    cfg_not_coop! {
444        fn poll_write_deferred(
445            self: Pin<&mut Self>,
446            cx: &mut task::Context<'_>,
447            buf: &[u8],
448            wakers: &mut Wakers,
449        ) -> Poll<std::io::Result<usize>> {
450            ready!(crate::trace::trace_leaf(cx));
451            self.poll_write_internal(cx, buf, wakers)
452        }
453    }
454
455    cfg_coop! {
456        fn poll_write_vectored_deferred(
457            self: Pin<&mut Self>,
458            cx: &mut task::Context<'_>,
459            bufs: &[std::io::IoSlice<'_>],
460            wakers: &mut Wakers,
461        ) -> Poll<Result<usize, std::io::Error>> {
462            ready!(crate::trace::trace_leaf(cx));
463            let coop = ready!(crate::task::coop::poll_proceed(cx));
464
465            let ret = self.poll_write_vectored_internal(cx, bufs, wakers);
466            if ret.is_ready() {
467                coop.made_progress();
468            }
469            ret
470        }
471    }
472
473    cfg_not_coop! {
474        fn poll_write_vectored_deferred(
475            self: Pin<&mut Self>,
476            cx: &mut task::Context<'_>,
477            bufs: &[std::io::IoSlice<'_>],
478            wakers: &mut Wakers,
479        ) -> Poll<Result<usize, std::io::Error>> {
480            ready!(crate::trace::trace_leaf(cx));
481            self.poll_write_vectored_internal(cx, bufs, wakers)
482        }
483    }
484}
485
486impl AsyncRead for SimplexStream {
487    fn poll_read(
488        self: Pin<&mut Self>,
489        cx: &mut task::Context<'_>,
490        buf: &mut ReadBuf<'_>,
491    ) -> Poll<std::io::Result<()>> {
492        let mut wakers = Wakers::default();
493        let ret = self.poll_read_deferred(cx, buf, &mut wakers);
494        wakers.wake();
495        ret
496    }
497}
498
499impl AsyncWrite for SimplexStream {
500    fn poll_write(
501        self: Pin<&mut Self>,
502        cx: &mut task::Context<'_>,
503        buf: &[u8],
504    ) -> Poll<std::io::Result<usize>> {
505        let mut wakers = Wakers::default();
506        let ret = self.poll_write_deferred(cx, buf, &mut wakers);
507        wakers.wake();
508        ret
509    }
510
511    fn poll_write_vectored(
512        self: Pin<&mut Self>,
513        cx: &mut task::Context<'_>,
514        bufs: &[std::io::IoSlice<'_>],
515    ) -> Poll<Result<usize, std::io::Error>> {
516        let mut wakers = Wakers::default();
517        let ret = self.poll_write_vectored_deferred(cx, bufs, &mut wakers);
518        wakers.wake();
519        ret
520    }
521
522    fn is_write_vectored(&self) -> bool {
523        true
524    }
525
526    fn poll_flush(self: Pin<&mut Self>, _: &mut task::Context<'_>) -> Poll<std::io::Result<()>> {
527        Poll::Ready(Ok(()))
528    }
529
530    fn poll_shutdown(
531        mut self: Pin<&mut Self>,
532        _: &mut task::Context<'_>,
533    ) -> Poll<std::io::Result<()>> {
534        if let Some(waker) = self.close_write() {
535            waker.wake();
536        }
537        Poll::Ready(Ok(()))
538    }
539}