reactor/poller/
mod.rs

1// Library for concurrent I/O resource management using reactor pattern.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2021-2023 by
6//     Dr. Maxim Orlovsky <orlovsky@ubideco.org>
7//     Alexis Sellier <alexis@cloudhead.io>
8//
9// Copyright 2022-2023 UBIDECO Institute, Switzerland
10// Copyright 2021 Alexis Sellier <alexis@cloudhead.io>
11//
12// Licensed under the Apache License, Version 2.0 (the "License");
13// you may not use this file except in compliance with the License.
14// You may obtain a copy of the License at
15//
16//     http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the License is distributed on an "AS IS" BASIS,
20// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21// See the License for the specific language governing permissions and
22// limitations under the License.
23
24//! OS and implementation-specific poll engines.
25
26#[cfg(feature = "popol")]
27pub mod popol;
28
29use std::fmt::{self, Display, Formatter};
30use std::os::unix::io::AsRawFd;
31use std::time::Duration;
32use std::{io, ops};
33
34use crate::resource::Io;
35use crate::ResourceId;
36
37/// Information about I/O events which has happened for a resource.
38#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
39pub struct IoType {
40    /// Specifies whether I/O source has data to read.
41    pub read: bool,
42    /// Specifies whether I/O source is ready for write operations.
43    pub write: bool,
44}
45
46impl IoType {
47    /// Indicates no I/O operations are tracked.
48    pub fn none() -> Self {
49        Self {
50            read: false,
51            write: false,
52        }
53    }
54
55    /// Indicates interest in only read I/O events.
56    pub fn read_only() -> Self {
57        Self {
58            read: true,
59            write: false,
60        }
61    }
62
63    /// Indicates interest in only write I/O events.
64    pub fn write_only() -> Self {
65        Self {
66            read: false,
67            write: true,
68        }
69    }
70
71    /// Indicates interest in both read and write I/O events.
72    pub fn read_write() -> Self {
73        Self {
74            read: true,
75            write: true,
76        }
77    }
78
79    /// Indicates no I/O operations has happened on a resource.
80    pub fn is_none(self) -> bool { !self.read && !self.write }
81    /// Indicates data available to be read from a resource.
82    pub fn is_read_only(self) -> bool { self.read && !self.write }
83    /// Indicates that the resource is ready to accept data.
84    pub fn is_write_only(self) -> bool { !self.read && self.write }
85    /// Indicates that the resource can accept data - and has aa data which can be read.
86    pub fn is_read_write(self) -> bool { self.read && self.write }
87}
88
89impl ops::Not for IoType {
90    type Output = Self;
91
92    fn not(self) -> Self::Output {
93        Self {
94            read: !self.read,
95            write: !self.write,
96        }
97    }
98}
99
100impl Iterator for IoType {
101    type Item = Io;
102
103    fn next(&mut self) -> Option<Self::Item> {
104        if self.write {
105            self.write = false;
106            Some(Io::Write)
107        } else if self.read {
108            self.read = false;
109            Some(Io::Read)
110        } else {
111            None
112        }
113    }
114}
115
116impl Display for IoType {
117    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
118        if self.is_none() {
119            f.write_str("none")
120        } else if self.is_read_write() {
121            f.write_str("read-write")
122        } else if self.read {
123            f.write_str("read")
124        } else if self.write {
125            f.write_str("write")
126        } else {
127            unreachable!()
128        }
129    }
130}
131
132/// Reasons for the poll operation failure for a specific resource.
133#[derive(Copy, Clone, Debug, Display, Error)]
134#[display(doc_comments)]
135pub enum IoFail {
136    /// hung up (POSIX events {0:#b})
137    Connectivity(i16),
138    /// errored (POSIX events {0:#b})
139    Os(i16),
140}
141
142/// An engine providing `poll` syscall interface to the [`crate::Reactor`].
143///
144/// Since `poll` syscalls are platform-dependent and multiple crates can expose it with a different
145/// API and tradeoffs, the current library allows selection of a specific poll engine
146/// implementation.
147///
148/// To read I/O events from the engine please use its Iterator interface.
149pub trait Poll
150where
151    Self: Send + Iterator<Item = (ResourceId, Result<IoType, IoFail>)>,
152    for<'a> &'a mut Self: Iterator<Item = (ResourceId, Result<IoType, IoFail>)>,
153{
154    /// Waker type used by the poll provider.
155    type Waker: Waker;
156
157    /// Registers a waker object.
158    fn register_waker(&mut self, fd: &impl AsRawFd);
159    /// Registers a file-descriptor based resource for a poll.
160    fn register(&mut self, fd: &impl AsRawFd, interest: IoType) -> ResourceId;
161    /// Unregisters a file-descriptor based resource from a poll.
162    fn unregister(&mut self, id: ResourceId);
163    /// Subscribes for a specific set of events for a given file descriptor-backed resource (see
164    /// [`IoType`] for the details on event subscription).
165    fn set_interest(&mut self, id: ResourceId, interest: IoType) -> bool;
166
167    /// Runs single poll syscall over all registered resources with an optional timeout.
168    ///
169    /// # Returns
170    ///
171    /// Number of generated events.
172    fn poll(&mut self, timeout: Option<Duration>) -> io::Result<usize>;
173}
174
175/// Waker object provided by the poller.
176pub trait Waker {
177    /// Data type for sending wake signals to the poller.
178    type Send: WakerSend;
179    /// Data type for receiving wake signals inside the poller.
180    type Recv: WakerRecv;
181
182    /// Constructs pair of waker receiver and sender objects.
183    fn pair() -> Result<(Self::Send, Self::Recv), io::Error>;
184}
185
186/// Sending part of the waker.
187pub trait WakerSend: Send + Sync + Clone {
188    /// Awakes the poller to read events.
189    fn wake(&self) -> io::Result<()>;
190}
191
192/// Receiver part of the waker.
193pub trait WakerRecv: AsRawFd + Send + io::Read {
194    /// Resets the waker reader.
195    fn reset(&self);
196}