Mio 0.7.0 update (#435)
This commit is contained in:
parent
dfafcc09ac
commit
c5fc1a1493
@ -1,6 +1,7 @@
|
|||||||
# Version 0.17.5
|
# Version 0.17.5
|
||||||
- Improved support of keymodifier for linux, arrow keys, function keys, home keys etc.
|
- Improved support of keymodifier for linux, arrow keys, function keys, home keys etc.
|
||||||
- Add `SetTitle` command to change the terminal title.
|
- Add `SetTitle` command to change the terminal title.
|
||||||
|
- Mio 0.7 update
|
||||||
|
|
||||||
# Version 0.17.4
|
# Version 0.17.4
|
||||||
- Add macros for `Colorize` and `Styler` impls, add an impl for `String`
|
- Add macros for `Colorize` and `Styler` impls, add an impl for `String`
|
||||||
|
@ -54,8 +54,8 @@ crossterm_winapi = "0.6.1"
|
|||||||
#
|
#
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
mio = "0.6"
|
mio = {version="0.7", features=["os-poll"]}
|
||||||
signal-hook = { version = "0.1.15", features = ["mio-support"] }
|
signal-hook = { version = "0.1.15", features = ["mio-0_7-support"] }
|
||||||
|
|
||||||
#
|
#
|
||||||
# Dev dependencies (examples, ...)
|
# Dev dependencies (examples, ...)
|
||||||
|
@ -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 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")]
|
#[cfg(feature = "event-stream")]
|
||||||
use super::super::sys::Waker;
|
use super::super::sys::Waker;
|
||||||
@ -45,34 +45,17 @@ impl UnixInternalEventSource {
|
|||||||
|
|
||||||
pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> Result<Self> {
|
pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> Result<Self> {
|
||||||
let poll = Poll::new()?;
|
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_raw_fd = input_fd.raw_fd();
|
||||||
let tty_ev = EventedFd(&tty_raw_fd);
|
let mut tty_ev = SourceFd(&tty_raw_fd);
|
||||||
poll.register(&tty_ev, TTY_TOKEN, Ready::readable(), PollOpt::level())?;
|
registry.register(&mut tty_ev, TTY_TOKEN, Interest::READABLE)?;
|
||||||
|
|
||||||
let signals = Signals::new(&[signal_hook::SIGWINCH])?;
|
let mut signals = Signals::new(&[signal_hook::SIGWINCH])?;
|
||||||
poll.register(&signals, SIGNAL_TOKEN, Ready::readable(), PollOpt::level())?;
|
registry.register(&mut signals, SIGNAL_TOKEN, Interest::READABLE)?;
|
||||||
|
|
||||||
#[cfg(feature = "event-stream")]
|
#[cfg(feature = "event-stream")]
|
||||||
let waker = Waker::new()?;
|
let mut waker = Waker::new(registry, WAKE_TOKEN)?;
|
||||||
#[cfg(feature = "event-stream")]
|
|
||||||
poll.register(&waker, WAKE_TOKEN, Ready::readable(), PollOpt::level())?;
|
|
||||||
|
|
||||||
Ok(UnixInternalEventSource {
|
Ok(UnixInternalEventSource {
|
||||||
poll,
|
poll,
|
||||||
@ -107,20 +90,28 @@ impl EventSource for UnixInternalEventSource {
|
|||||||
for token in self.events.iter().map(|x| x.token()) {
|
for token in self.events.iter().map(|x| x.token()) {
|
||||||
match token {
|
match token {
|
||||||
TTY_TOKEN => {
|
TTY_TOKEN => {
|
||||||
let read_count = self.tty_fd.read(&mut self.tty_buffer, TTY_BUFFER_SIZE)?;
|
loop {
|
||||||
|
match self.tty_fd.read(&mut self.tty_buffer, TTY_BUFFER_SIZE) {
|
||||||
|
Ok(read_count) => {
|
||||||
if read_count > 0 {
|
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.parser.advance(
|
||||||
&self.tty_buffer[..read_count],
|
&self.tty_buffer[..read_count],
|
||||||
additional_input_available,
|
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() {
|
if let Some(event) = self.parser.next() {
|
||||||
return Ok(Some(event));
|
return Ok(Some(event));
|
||||||
@ -149,7 +140,6 @@ impl EventSource for UnixInternalEventSource {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "event-stream")]
|
#[cfg(feature = "event-stream")]
|
||||||
WAKE_TOKEN => {
|
WAKE_TOKEN => {
|
||||||
let _ = self.waker.reset();
|
|
||||||
return Err(std::io::Error::new(
|
return Err(std::io::Error::new(
|
||||||
std::io::ErrorKind::Interrupted,
|
std::io::ErrorKind::Interrupted,
|
||||||
"Poll operation was woken up by `Waker::wake`",
|
"Poll operation was woken up by `Waker::wake`",
|
||||||
|
@ -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 std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use mio::{Evented, Poll, PollOpt, Ready, Registration, SetReadiness, Token};
|
use mio::{Registry, Token};
|
||||||
|
|
||||||
use crate::Result;
|
use crate::{ErrorKind, 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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allows to wake up the `mio::Poll::poll()` method.
|
/// Allows to wake up the `mio::Poll::poll()` method.
|
||||||
|
/// This type wraps `mio::Waker`, for more information see its documentation.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct Waker {
|
pub(crate) struct Waker {
|
||||||
inner: Arc<Mutex<WakerInner>>,
|
inner: Arc<Mutex<mio::Waker>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Waker {
|
impl Waker {
|
||||||
/// Creates a new waker.
|
/// Create a new `Waker`.
|
||||||
///
|
pub(crate) fn new(registry: &Registry, waker_token: Token) -> Result<Self> {
|
||||||
/// `Waker` implements the `mio::Evented` trait and you have to register
|
|
||||||
/// it in order to use it.
|
|
||||||
pub(crate) fn new() -> Result<Self> {
|
|
||||||
Ok(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()`.
|
/// Readiness is set to `Ready::readable()`.
|
||||||
pub(crate) fn wake(&self) -> Result<()> {
|
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.
|
/// 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<()> {
|
pub(crate) fn reset(&self) -> Result<()> {
|
||||||
self.inner.lock().unwrap().reset()
|
Ok(())
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user