loop driver: Decouple from concrete state
This commit is contained in:
@ -18,21 +18,25 @@
|
|||||||
|
|
||||||
use crate::event_loop;
|
use crate::event_loop;
|
||||||
use crate::logging;
|
use crate::logging;
|
||||||
use crate::main::Commands;
|
use crate::state::Application;
|
||||||
use crate::state::{ Application, Event };
|
|
||||||
use glib;
|
use glib;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
use super::{ActorState, Outcome};
|
||||||
|
|
||||||
// Traits
|
// Traits
|
||||||
use crate::logging::Warn;
|
use crate::logging::Warn;
|
||||||
|
use super::Event;
|
||||||
|
|
||||||
|
|
||||||
/// Type of the sender that waits for external events
|
type UISender<S> = glib::Sender<
|
||||||
type Sender = mpsc::Sender<Event>;
|
<
|
||||||
/// Type of the sender that waits for internal state changes
|
<S as ActorState>::Outcome as Outcome
|
||||||
type UISender = glib::Sender<Commands>;
|
>::Commands
|
||||||
|
>;
|
||||||
|
|
||||||
|
pub type Threaded = Threaded_<Application>;
|
||||||
|
|
||||||
/// This loop driver spawns a new thread which updates the state in a loop,
|
/// This loop driver spawns a new thread which updates the state in a loop,
|
||||||
/// in response to incoming events.
|
/// in response to incoming events.
|
||||||
@ -43,12 +47,27 @@ type UISender = glib::Sender<Commands>;
|
|||||||
// This can/should be abstracted over Event and Commands,
|
// This can/should be abstracted over Event and Commands,
|
||||||
// so that the C call-ins can be thrown away from here and defined near events.
|
// so that the C call-ins can be thrown away from here and defined near events.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Threaded {
|
pub struct Threaded_<S>
|
||||||
thread: Sender,
|
where
|
||||||
|
S: ActorState + Send,
|
||||||
|
S::Event: Send,
|
||||||
|
<S::Outcome as Outcome>::Commands: Send,
|
||||||
|
{
|
||||||
|
/// Waits for external events
|
||||||
|
thread: mpsc::Sender<S::Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Threaded {
|
impl<S> Threaded_<S>
|
||||||
pub fn new(ui: UISender, initial_state: Application) -> Self {
|
where
|
||||||
|
// Not sure why this needs 'static. It's already owned.
|
||||||
|
S: ActorState + Send + 'static,
|
||||||
|
S::Event: Send,
|
||||||
|
<S::Outcome as Outcome>::Commands: Send,
|
||||||
|
{
|
||||||
|
pub fn new(
|
||||||
|
ui: UISender<S>,
|
||||||
|
initial_state: S,
|
||||||
|
) -> Self {
|
||||||
let (sender, receiver) = mpsc::channel();
|
let (sender, receiver) = mpsc::channel();
|
||||||
let saved_sender = sender.clone();
|
let saved_sender = sender.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
@ -71,13 +90,16 @@ impl Threaded {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send(&self, event: Event) -> Result<(), mpsc::SendError<Event>> {
|
pub fn send(&self, event: S::Event) -> Result<(), mpsc::SendError<S::Event>> {
|
||||||
self.thread.send(event)
|
self.thread.send(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_loop_event(loop_sender: &Sender, state: event_loop::State<Application>, event: Event, ui: &UISender)
|
fn handle_loop_event(
|
||||||
-> event_loop::State<Application>
|
loop_sender: &mpsc::Sender<S::Event>,
|
||||||
{
|
state: event_loop::State<S>,
|
||||||
|
event: S::Event,
|
||||||
|
ui: &UISender<S>,
|
||||||
|
) -> event_loop::State<S> {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
let (new_state, commands) = event_loop::handle_event(state.clone(), event, now);
|
let (new_state, commands) = event_loop::handle_event(state.clone(), event, now);
|
||||||
@ -94,12 +116,15 @@ impl Threaded {
|
|||||||
new_state
|
new_state
|
||||||
}
|
}
|
||||||
|
|
||||||
fn schedule_timeout_wake(loop_sender: &Sender, when: Instant) {
|
fn schedule_timeout_wake(
|
||||||
|
loop_sender: &mpsc::Sender<S::Event>,
|
||||||
|
when: Instant,
|
||||||
|
) {
|
||||||
let sender = loop_sender.clone();
|
let sender = loop_sender.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
thread::sleep(when - now);
|
thread::sleep(when - now);
|
||||||
sender.send(Event::TimeoutReached(when))
|
sender.send(S::Event::new_timeout_reached(when))
|
||||||
.or_warn(&mut logging::Print, logging::Problem::Warning, "Can't wake visibility manager");
|
.or_warn(&mut logging::Print, logging::Problem::Warning, "Can't wake visibility manager");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -109,7 +134,7 @@ impl Threaded {
|
|||||||
mod c {
|
mod c {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::state::Presence;
|
use crate::state::{Event, Presence};
|
||||||
use crate::state::LayoutChoice;
|
use crate::state::LayoutChoice;
|
||||||
use crate::state::visibility;
|
use crate::state::visibility;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
|||||||
@ -45,6 +45,7 @@ use std::time::{ Duration, Instant };
|
|||||||
/// Carries the incoming data to affect the actor state,
|
/// Carries the incoming data to affect the actor state,
|
||||||
/// plus an event to help schedule timed events.
|
/// plus an event to help schedule timed events.
|
||||||
pub trait Event: Clone {
|
pub trait Event: Clone {
|
||||||
|
fn new_timeout_reached(when: Instant) -> Self;
|
||||||
/// Returns the value of the reached timeout, if this event carries the timeout.
|
/// Returns the value of the reached timeout, if this event carries the timeout.
|
||||||
fn get_timeout_reached(&self) -> Option<Instant>;
|
fn get_timeout_reached(&self) -> Option<Instant>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,6 +83,10 @@ pub enum Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl event_loop::Event for Event {
|
impl event_loop::Event for Event {
|
||||||
|
fn new_timeout_reached(when: Instant) -> Self {
|
||||||
|
Self::TimeoutReached(when)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_timeout_reached(&self) -> Option<Instant> {
|
fn get_timeout_reached(&self) -> Option<Instant> {
|
||||||
match self {
|
match self {
|
||||||
Self::TimeoutReached(when) => Some(*when),
|
Self::TimeoutReached(when) => Some(*when),
|
||||||
|
|||||||
Reference in New Issue
Block a user