Skip to content

Non-blocking variants of IpcReceiverSet::select #434

@glyn

Description

@glyn

IPC channel multiplexing needs non-blocking variants of IpcReceiverSet::select to support SubReceiverSet (and thereby routing). Non-blocking variants of select may also be useful more generally and we should avoid biasing the variants towards multiplexing.

glyn/ipc-channel-mux#4 requires non-blocking select (without a timeout) whereas glyn/ipc-channel-mux#2 and glyn/ipc-channel-mux#5 require non-blocking select with timeout.

The API and semantics of these variants should be a cross between the API/semantics of IpcReceiverSet::select and the non-blocking API/semantics of IpcReceiver::try_recv and IpcReceiver::try_recv_timeout (see "Existing APIs" below), probably along the following lines:

#[derive(Debug)]
pub enum TrySelectError {
    IoError(io::Error),
    Empty,
}

impl IpcReceiverSet {
    pub fn try_select(&mut self) -> Result<Vec<IpcSelectionResult>, TrySelectError> {...}

    pub fn try_select_timeout(&mut self, duration: Duration) -> Result<Vec<IpcSelectionResult>, TrySelectError> {...}

    ...
}

Existing APIs

Existing select API:

impl IpcReceiverSet {
    /// Wait for IPC messages received on any of the receivers in the set. The
    /// method will return multiple events. An event may be either a message
    /// received or a channel closed event.
    ///
    /// [IpcReceiver]: struct.IpcReceiver.html
    pub fn select(&mut self) -> Result<Vec<IpcSelectionResult>, io::Error> {...}

    ...
}

Existing IpcReceiver blocking and non-blocking API:

#[derive(Debug)]
pub enum TryRecvError {
    IpcError(IpcError),
    Empty,
}

impl<T> IpcReceiver<T>
where
    T: for<'de> Deserialize<'de> + Serialize,
{
    /// Blocking receive.
    pub fn recv(&self) -> Result<T, IpcError> {
        self.os_receiver.recv()?.to().map_err(IpcError::Bincode)
    }

    /// Non-blocking receive
    pub fn try_recv(&self) -> Result<T, TryRecvError> {...}

    /// Blocks for up to the specified duration attempting to receive a message.
    ///
    /// This may block for longer than the specified duration if the channel is busy. If your timeout
    /// exceeds the duration that your operating system can represent in milliseconds, this may
    /// block forever. At the time of writing, the smallest duration that may trigger this behavior
    /// is over 24 days.
    pub fn try_recv_timeout(&self, duration: Duration) -> Result<T, TryRecvError> {...}

    ...
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions