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}