pub struct Sender { /* private fields */ }
Expand description

Writing end of a Unix pipe.

It can be constructed from a FIFO file with OpenOptions::open_sender.

Opening a named pipe for writing involves a few steps. Call to OpenOptions::open_sender might fail with an error indicating different things:

  • io::ErrorKind::NotFound - There is no file at the specified path.
  • io::ErrorKind::InvalidInput - The file exists, but it is not a FIFO.
  • ENXIO - The file is a FIFO, but no process has it open for reading. Sleep for a while and try again.
  • Other OS errors not specific to opening FIFO files.

Opening a Sender from a FIFO file should look like this:

use tokio::net::unix::pipe;
use tokio::time::{self, Duration};

const FIFO_NAME: &str = "path/to/a/fifo";

// Wait for a reader to open the file.
let tx = loop {
    match pipe::OpenOptions::new().open_sender(FIFO_NAME) {
        Ok(tx) => break tx,
        Err(e) if e.raw_os_error() == Some(libc::ENXIO) => {},
        Err(e) => return Err(e.into()),
    }

    time::sleep(Duration::from_millis(50)).await;
};

On Linux, it is possible to create a Sender without waiting in a sleeping loop. This is done by opening a named pipe in read-write access mode with OpenOptions::read_write. This way, a Sender can at the same time hold both a writing end and a reading end, and the latter allows to open a FIFO without ENXIO error since the pipe is open for reading as well.

Sender cannot be used to read from a pipe, so in practice the read access is only used when a FIFO is opened. However, using a Sender in read-write mode may lead to lost data, because written data will be dropped by the system as soon as all pipe ends are closed. To avoid lost data you have to make sure that a reading end has been opened before dropping a Sender.

Note that using read-write access mode with FIFO files is not defined by the POSIX standard and it is only guaranteed to work on Linux.

use tokio::io::AsyncWriteExt;
use tokio::net::unix::pipe;

const FIFO_NAME: &str = "path/to/a/fifo";

let mut tx = pipe::OpenOptions::new()
    .read_write(true)
    .open_sender(FIFO_NAME)?;

// Asynchronously write to the pipe before a reader.
tx.write_all(b"hello world").await?;

Implementations§

source§

impl Sender

source

pub fn from_file(file: File) -> Result<Sender, Error>

Creates a new Sender from a File.

This function is intended to construct a pipe from a File representing a special FIFO file. It will check if the file is a pipe and has write access, set it in non-blocking mode and perform the conversion.

Errors

Fails with io::ErrorKind::InvalidInput if the file is not a pipe or it does not have write access. Also fails with any standard OS error if it occurs.

Panics

This function panics if it is not called from within a runtime with IO enabled.

The runtime is usually set implicitly when this function is called from a future driven by a tokio runtime, otherwise runtime can be set explicitly with Runtime::enter function.

source

pub fn from_file_unchecked(file: File) -> Result<Sender, Error>

Creates a new Sender from a File without checking pipe properties.

This function is intended to construct a pipe from a File representing a special FIFO file. The conversion assumes nothing about the underlying file; it is left up to the user to make sure it is opened with write access, represents a pipe and is set in non-blocking mode.

Examples
use tokio::net::unix::pipe;
use std::fs::OpenOptions;
use std::os::unix::fs::{FileTypeExt, OpenOptionsExt};

const FIFO_NAME: &str = "path/to/a/fifo";

let file = OpenOptions::new()
    .write(true)
    .custom_flags(libc::O_NONBLOCK)
    .open(FIFO_NAME)?;
if file.metadata()?.file_type().is_fifo() {
    let tx = pipe::Sender::from_file_unchecked(file)?;
    /* use the Sender */
}
Panics

This function panics if it is not called from within a runtime with IO enabled.

The runtime is usually set implicitly when this function is called from a future driven by a tokio runtime, otherwise runtime can be set explicitly with Runtime::enter function.

source

pub async fn ready(&self, interest: Interest) -> Result<Ready, Error>

Waits for any of the requested ready states.

This function can be used instead of writable() to check the returned ready set for Ready::WRITABLE and Ready::WRITE_CLOSED events.

The function may complete without the pipe being ready. This is a false-positive and attempting an operation will return with io::ErrorKind::WouldBlock. The function can also return with an empty Ready set, so you should always check the returned value and possibly wait again if the requested states are not set.

Cancel safety

This method is cancel safe. Once a readiness event occurs, the method will continue to return immediately until the readiness event is consumed by an attempt to write that fails with WouldBlock or Poll::Pending.

source

pub async fn writable(&self) -> Result<(), Error>

Waits for the pipe to become writable.

This function is equivalent to ready(Interest::WRITABLE) and is usually paired with try_write().

Examples
use tokio::net::unix::pipe;
use std::io;

#[tokio::main]
async fn main() -> io::Result<()> {
    // Open a writing end of a fifo
    let tx = pipe::OpenOptions::new().open_sender("path/to/a/fifo")?;

    loop {
        // Wait for the pipe to be writable
        tx.writable().await?;

        // Try to write data, this may still fail with `WouldBlock`
        // if the readiness event is a false positive.
        match tx.try_write(b"hello world") {
            Ok(n) => {
                break;
            }
            Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
                continue;
            }
            Err(e) => {
                return Err(e.into());
            }
        }
    }

    Ok(())
}
source

pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for write readiness.

If the pipe is not currently ready for writing, this method will store a clone of the Waker from the provided Context. When the pipe becomes ready for writing, Waker::wake will be called on the waker.

Note that on multiple calls to poll_write_ready or poll_write, only the Waker from the Context passed to the most recent call is scheduled to receive a wakeup.

This function is intended for cases where creating and pinning a future via writable is not feasible. Where possible, using writable is preferred, as this supports polling from multiple tasks at once.

Return value

The function returns:

  • Poll::Pending if the pipe is not ready for writing.
  • Poll::Ready(Ok(())) if the pipe is ready for writing.
  • Poll::Ready(Err(e)) if an error is encountered.
Errors

This function may encounter any standard I/O error except WouldBlock.

source

pub fn try_write(&self, buf: &[u8]) -> Result<usize, Error>

Tries to write a buffer to the pipe, returning how many bytes were written.

The function will attempt to write the entire contents of buf, but only part of the buffer may be written. If the length of buf is not greater than PIPE_BUF (an OS constant, 4096 under Linux), then the write is guaranteed to be atomic, i.e. either the entire content of buf will be written or this method will fail with WouldBlock. There is no such guarantee if buf is larger than PIPE_BUF.

This function is usually paired with writable.

Return

If data is successfully written, Ok(n) is returned, where n is the number of bytes written. If the pipe is not ready to write data, Err(io::ErrorKind::WouldBlock) is returned.

Examples
use tokio::net::unix::pipe;
use std::io;

#[tokio::main]
async fn main() -> io::Result<()> {
    // Open a writing end of a fifo
    let tx = pipe::OpenOptions::new().open_sender("path/to/a/fifo")?;

    loop {
        // Wait for the pipe to be writable
        tx.writable().await?;

        // Try to write data, this may still fail with `WouldBlock`
        // if the readiness event is a false positive.
        match tx.try_write(b"hello world") {
            Ok(n) => {
                break;
            }
            Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
                continue;
            }
            Err(e) => {
                return Err(e.into());
            }
        }
    }

    Ok(())
}
source

pub fn try_write_vectored(&self, buf: &[IoSlice<'_>]) -> Result<usize, Error>

Tries to write several buffers to the pipe, returning how many bytes were written.

Data is written from each buffer in order, with the final buffer read from possible being only partially consumed. This method behaves equivalently to a single call to try_write() with concatenated buffers.

If the total length of buffers is not greater than PIPE_BUF (an OS constant, 4096 under Linux), then the write is guaranteed to be atomic, i.e. either the entire contents of buffers will be written or this method will fail with WouldBlock. There is no such guarantee if the total length of buffers is greater than PIPE_BUF.

This function is usually paired with writable.

Return

If data is successfully written, Ok(n) is returned, where n is the number of bytes written. If the pipe is not ready to write data, Err(io::ErrorKind::WouldBlock) is returned.

Examples
use tokio::net::unix::pipe;
use std::io;

#[tokio::main]
async fn main() -> io::Result<()> {
    // Open a writing end of a fifo
    let tx = pipe::OpenOptions::new().open_sender("path/to/a/fifo")?;

    let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")];

    loop {
        // Wait for the pipe to be writable
        tx.writable().await?;

        // Try to write data, this may still fail with `WouldBlock`
        // if the readiness event is a false positive.
        match tx.try_write_vectored(&bufs) {
            Ok(n) => {
                break;
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                continue;
            }
            Err(e) => {
                return Err(e.into());
            }
        }
    }

    Ok(())
}

Trait Implementations§

source§

impl AsFd for Sender

source§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
source§

impl AsRawFd for Sender

source§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
source§

impl AsyncWrite for Sender

source§

fn poll_write( self: Pin<&mut Sender>, cx: &mut Context<'_>, buf: &[u8] ) -> Poll<Result<usize, Error>>

Attempt to write bytes from buf into the object. Read more
source§

fn poll_write_vectored( self: Pin<&mut Sender>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>] ) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored implementation. Read more
source§

fn poll_flush( self: Pin<&mut Sender>, _: &mut Context<'_> ) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach their destination. Read more
source§

fn poll_shutdown( self: Pin<&mut Sender>, _: &mut Context<'_> ) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when the I/O connection has completely shut down. Read more
source§

impl Debug for Sender

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Any for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

§

fn type_name(&self) -> &'static str

§

impl<T> AnySync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

§

impl<T> ArchivePointee for T

§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
§

impl<T> AsFilelike for T
where T: AsFd,

§

fn as_filelike(&self) -> BorrowedFd<'_>

Borrows the reference. Read more
§

fn as_filelike_view<Target>(&self) -> FilelikeView<'_, Target>
where Target: FilelikeViewType,

Return a borrowing view of a resource which dereferences to a &Target. Read more
§

impl<T> AsRawFilelike for T
where T: AsRawFd,

§

fn as_raw_filelike(&self) -> i32

Returns the raw value.
§

impl<T> AsRawSocketlike for T
where T: AsRawFd,

§

fn as_raw_socketlike(&self) -> i32

Returns the raw value.
§

impl<T> AsSocketlike for T
where T: AsFd,

§

fn as_socketlike(&self) -> BorrowedFd<'_>

Borrows the reference.
§

fn as_socketlike_view<Target>(&self) -> SocketlikeView<'_, Target>
where Target: SocketlikeViewType,

Return a borrowing view of a resource which dereferences to a &Target. Read more
source§

impl<W> AsyncWriteExt for W
where W: AsyncWrite + ?Sized,

source§

fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
where Self: Unpin,

Writes a buffer into this writer, returning how many bytes were written. Read more
source§

fn write_vectored<'a, 'b>( &'a mut self, bufs: &'a [IoSlice<'b>] ) -> WriteVectored<'a, 'b, Self>
where Self: Unpin,

Like write, except that it writes from a slice of buffers. Read more
source§

fn write_buf<B, 'a>(&'a mut self, src: &'a mut B) -> WriteBuf<'a, Self, B>
where Self: Sized + Unpin, B: Buf,

Writes a buffer into this writer, advancing the buffer’s internal cursor. Read more
source§

fn write_all_buf<B, 'a>( &'a mut self, src: &'a mut B ) -> WriteAllBuf<'a, Self, B>
where Self: Sized + Unpin, B: Buf,

Attempts to write an entire buffer into this writer. Read more
source§

fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self>
where Self: Unpin,

Attempts to write an entire buffer into this writer. Read more
source§

fn write_u8(&mut self, n: u8) -> WriteU8<&mut Self>
where Self: Unpin,

Writes an unsigned 8-bit integer to the underlying writer. Read more
source§

fn write_i8(&mut self, n: i8) -> WriteI8<&mut Self>
where Self: Unpin,

Writes a signed 8-bit integer to the underlying writer. Read more
source§

fn write_u16(&mut self, n: u16) -> WriteU16<&mut Self>
where Self: Unpin,

Writes an unsigned 16-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_i16(&mut self, n: i16) -> WriteI16<&mut Self>
where Self: Unpin,

Writes a signed 16-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_u32(&mut self, n: u32) -> WriteU32<&mut Self>
where Self: Unpin,

Writes an unsigned 32-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_i32(&mut self, n: i32) -> WriteI32<&mut Self>
where Self: Unpin,

Writes a signed 32-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_u64(&mut self, n: u64) -> WriteU64<&mut Self>
where Self: Unpin,

Writes an unsigned 64-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_i64(&mut self, n: i64) -> WriteI64<&mut Self>
where Self: Unpin,

Writes an signed 64-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_u128(&mut self, n: u128) -> WriteU128<&mut Self>
where Self: Unpin,

Writes an unsigned 128-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_i128(&mut self, n: i128) -> WriteI128<&mut Self>
where Self: Unpin,

Writes an signed 128-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_f32(&mut self, n: f32) -> WriteF32<&mut Self>
where Self: Unpin,

Writes an 32-bit floating point type in big-endian order to the underlying writer. Read more
source§

fn write_f64(&mut self, n: f64) -> WriteF64<&mut Self>
where Self: Unpin,

Writes an 64-bit floating point type in big-endian order to the underlying writer. Read more
source§

fn write_u16_le(&mut self, n: u16) -> WriteU16Le<&mut Self>
where Self: Unpin,

Writes an unsigned 16-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_i16_le(&mut self, n: i16) -> WriteI16Le<&mut Self>
where Self: Unpin,

Writes a signed 16-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_u32_le(&mut self, n: u32) -> WriteU32Le<&mut Self>
where Self: Unpin,

Writes an unsigned 32-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_i32_le(&mut self, n: i32) -> WriteI32Le<&mut Self>
where Self: Unpin,

Writes a signed 32-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_u64_le(&mut self, n: u64) -> WriteU64Le<&mut Self>
where Self: Unpin,

Writes an unsigned 64-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_i64_le(&mut self, n: i64) -> WriteI64Le<&mut Self>
where Self: Unpin,

Writes an signed 64-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_u128_le(&mut self, n: u128) -> WriteU128Le<&mut Self>
where Self: Unpin,

Writes an unsigned 128-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_i128_le(&mut self, n: i128) -> WriteI128Le<&mut Self>
where Self: Unpin,

Writes an signed 128-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_f32_le(&mut self, n: f32) -> WriteF32Le<&mut Self>
where Self: Unpin,

Writes an 32-bit floating point type in little-endian order to the underlying writer. Read more
source§

fn write_f64_le(&mut self, n: f64) -> WriteF64Le<&mut Self>
where Self: Unpin,

Writes an 64-bit floating point type in little-endian order to the underlying writer. Read more
source§

fn flush(&mut self) -> Flush<'_, Self>
where Self: Unpin,

Flushes this output stream, ensuring that all intermediately buffered contents reach their destination. Read more
source§

fn shutdown(&mut self) -> Shutdown<'_, Self>
where Self: Unpin,

Shuts down the output stream, ensuring that the value can be dropped cleanly. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<F, W, T, D> Deserialize<With<T, W>, D> for F
where W: DeserializeWith<F, T, D>, D: Fallible + ?Sized, F: ?Sized,

§

fn deserialize( &self, deserializer: &mut D ) -> Result<With<T, W>, <D as Fallible>::Error>

Deserializes using the given deserializer
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FutureExt for T

§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<Stream> IsTerminal for Stream
where Stream: AsFd,

§

fn is_terminal(&self) -> bool

Returns true if this is a terminal. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> Pointee for T

§

type Metadata = ()

The type for metadata in pointers and references to Self.
source§

impl<T> Same for T

§

type Output = T

Should always be Self
§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Upcastable for T
where T: Any + Send + Sync + 'static,

§

fn upcast_any_ref(&self) -> &(dyn Any + 'static)

upcast ref
§

fn upcast_any_mut(&mut self) -> &mut (dyn Any + 'static)

upcast mut ref
§

fn upcast_any_box(self: Box<T>) -> Box<dyn Any>

upcast boxed dyn
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more