Mio 0.7.0 update (#435)

This commit is contained in:
Timon 2020-07-02 15:06:38 +02:00 committed by GitHub
parent dfafcc09ac
commit c5fc1a1493
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 120 deletions

View File

@ -1,6 +1,7 @@
# Version 0.17.5
- Improved support of keymodifier for linux, arrow keys, function keys, home keys etc.
- Add `SetTitle` command to change the terminal title.
- Mio 0.7 update
# Version 0.17.4
- Add macros for `Colorize` and `Styler` impls, add an impl for `String`

View File

@ -54,8 +54,8 @@ crossterm_winapi = "0.6.1"
#
[target.'cfg(unix)'.dependencies]
libc = "0.2"
mio = "0.6"
signal-hook = { version = "0.1.15", features = ["mio-support"] }
mio = {version="0.7", features=["os-poll"]}
signal-hook = { version = "0.1.15", features = ["mio-0_7-support"] }
#
# Dev dependencies (examples, ...)

View File

@ -1,8 +1,8 @@
use mio::{unix::EventedFd, Events, Poll, PollOpt, Ready, Token};
use mio::{unix::SourceFd, Events, Interest, Poll, Token};
use signal_hook::iterator::Signals;
use std::{collections::VecDeque, time::Duration};
use std::{collections::VecDeque, io, time::Duration};
use crate::Result;
use crate::{ErrorKind, Result};
#[cfg(feature = "event-stream")]
use super::super::sys::Waker;
@ -45,34 +45,17 @@ impl UnixInternalEventSource {
pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> Result<Self> {
let poll = Poll::new()?;
let mut registry = poll.registry();
// PollOpt::level vs PollOpt::edge mio documentation:
//
// > With edge-triggered events, operations must be performed on the Evented type until
// > WouldBlock is returned.
//
// TL;DR - DO NOT use PollOpt::edge.
//
// Because of the `try_read` nature (loop with returns) we can't use `PollOpt::edge`. All
// `Evented` handles MUST be registered with the `PollOpt::level`.
//
// If you have to use `PollOpt::edge` and there's no way how to do it with the `PollOpt::level`,
// be aware that the whole `TtyInternalEventSource` have to be rewritten
// (read everything from each `Evented`, process without returns, store all InternalEvent events
// into a buffer and then return first InternalEvent, etc.). Even these changes wont be
// enough, because `Poll::poll` wont fire again until additional `Evented` event happens and
// we can still have a buffer filled with InternalEvent events.
let tty_raw_fd = input_fd.raw_fd();
let tty_ev = EventedFd(&tty_raw_fd);
poll.register(&tty_ev, TTY_TOKEN, Ready::readable(), PollOpt::level())?;
let mut tty_ev = SourceFd(&tty_raw_fd);
registry.register(&mut tty_ev, TTY_TOKEN, Interest::READABLE)?;
let signals = Signals::new(&[signal_hook::SIGWINCH])?;
poll.register(&signals, SIGNAL_TOKEN, Ready::readable(), PollOpt::level())?;
let mut signals = Signals::new(&[signal_hook::SIGWINCH])?;
registry.register(&mut signals, SIGNAL_TOKEN, Interest::READABLE)?;
#[cfg(feature = "event-stream")]
let waker = Waker::new()?;
#[cfg(feature = "event-stream")]
poll.register(&waker, WAKE_TOKEN, Ready::readable(), PollOpt::level())?;
let mut waker = Waker::new(registry, WAKE_TOKEN)?;
Ok(UnixInternalEventSource {
poll,
@ -107,20 +90,28 @@ impl EventSource for UnixInternalEventSource {
for token in self.events.iter().map(|x| x.token()) {
match token {
TTY_TOKEN => {
let read_count = self.tty_fd.read(&mut self.tty_buffer, TTY_BUFFER_SIZE)?;
if read_count > 0 {
self.poll
.poll(&mut additional_input_events, Some(Duration::from_secs(0)))?;
let additional_input_available = additional_input_events
.iter()
.any(|event| event.token() == TTY_TOKEN);
self.parser.advance(
&self.tty_buffer[..read_count],
additional_input_available,
);
loop {
match self.tty_fd.read(&mut self.tty_buffer, TTY_BUFFER_SIZE) {
Ok(read_count) => {
if read_count > 0 {
self.parser.advance(
&self.tty_buffer[..read_count],
read_count == TTY_BUFFER_SIZE,
);
}
}
Err(ErrorKind::IoError(e)) => {
// No more data to read at the moment. We will receive another event
if e.kind() == io::ErrorKind::WouldBlock {
break;
}
// once more data is available to read.
else if e.kind() == io::ErrorKind::Interrupted {
continue;
}
}
Err(e) => return Err(e),
};
if let Some(event) = self.parser.next() {
return Ok(Some(event));
@ -149,7 +140,6 @@ impl EventSource for UnixInternalEventSource {
}
#[cfg(feature = "event-stream")]
WAKE_TOKEN => {
let _ = self.waker.reset();
return Err(std::io::Error::new(
std::io::ErrorKind::Interrupted,
"Poll operation was woken up by `Waker::wake`",

View File

@ -1,101 +1,39 @@
// TODO Replace with `mio::Waker` when the 0.7 is released (not available in 0.6).
use std::sync::{Arc, Mutex};
use mio::{Evented, Poll, PollOpt, Ready, Registration, SetReadiness, Token};
use mio::{Registry, Token};
use crate::Result;
#[derive(Debug)]
struct WakerInner {
registration: Registration,
set_readiness: SetReadiness,
}
impl WakerInner {
fn new() -> Self {
let (registration, set_readiness) = Registration::new2();
Self {
registration,
set_readiness,
}
}
fn wake(&self) -> Result<()> {
self.set_readiness.set_readiness(Ready::readable())?;
Ok(())
}
fn reset(&self) -> Result<()> {
self.set_readiness.set_readiness(Ready::empty())?;
Ok(())
}
}
use crate::{ErrorKind, Result};
/// Allows to wake up the `mio::Poll::poll()` method.
/// This type wraps `mio::Waker`, for more information see its documentation.
#[derive(Clone, Debug)]
pub(crate) struct Waker {
inner: Arc<Mutex<WakerInner>>,
inner: Arc<Mutex<mio::Waker>>,
}
impl Waker {
/// Creates a new waker.
///
/// `Waker` implements the `mio::Evented` trait and you have to register
/// it in order to use it.
pub(crate) fn new() -> Result<Self> {
/// Create a new `Waker`.
pub(crate) fn new(registry: &Registry, waker_token: Token) -> Result<Self> {
Ok(Self {
inner: Arc::new(Mutex::new(WakerInner::new())),
inner: Arc::new(Mutex::new(mio::Waker::new(registry, waker_token)?)),
})
}
/// Wakes the `mio::Poll.poll()` method.
/// Wake up the [`Poll`] associated with this `Waker`.
///
/// Readiness is set to `Ready::readable()`.
pub(crate) fn wake(&self) -> Result<()> {
self.inner.lock().unwrap().wake()
self.inner
.lock()
.unwrap()
.wake()
.map_err(|e| ErrorKind::IoError(e))
}
/// Resets the state so the same waker can be reused.
///
/// Readiness is set back to `Ready::empty()`.
/// This function is not impl
pub(crate) fn reset(&self) -> Result<()> {
self.inner.lock().unwrap().reset()
}
}
impl Evented for Waker {
fn register(
&self,
poll: &Poll,
token: Token,
interest: Ready,
opts: PollOpt,
) -> ::std::io::Result<()> {
self.inner
.lock()
.unwrap()
.registration
.register(poll, token, interest, opts)
}
fn reregister(
&self,
poll: &Poll,
token: Token,
interest: Ready,
opts: PollOpt,
) -> ::std::io::Result<()> {
self.inner
.lock()
.unwrap()
.registration
.reregister(poll, token, interest, opts)
}
#[allow(deprecated)]
fn deregister(&self, poll: &Poll) -> ::std::io::Result<()> {
self.inner.lock().unwrap().registration.deregister(poll)
Ok(())
}
}