Commit e76cfc7c authored by Ralf's avatar Ralf
Browse files

move stuff around

parent bb1c8912
......@@ -12,3 +12,9 @@ pub trait Actor<T> {
fn act(&mut self, t: T);
}
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum LockAction {
PressLock,
PressUnlock,
Release,
}
......@@ -4,7 +4,56 @@ use chan::Receiver;
use util::timeout_chan;
use input::Event;
use super::event_handler::*;
#[must_use]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum HandlerResult {
Continue,
QuitLoop,
}
// TODO: Consider making this a trait, or a type alias for a raw FnMut
pub struct EventHandler<'a> {
run: Box<FnMut(Event) -> HandlerResult + 'a>,
}
impl<'a> EventHandler<'a> {
pub fn new<F>(f: F) -> Self
where F: FnMut(Event) -> HandlerResult + 'a
{
EventHandler { run: Box::new(f) }
}
pub fn new_boxed(f: Box<FnMut(Event) -> HandlerResult + 'a>) -> Self {
EventHandler { run: f }
}
pub fn new_safe<F>(mut f: F) -> Self
where F: FnMut(Event) + 'a
{
EventHandler {
run: Box::new(move |ev| {
f(ev);
HandlerResult::Continue
}),
}
}
pub fn new_safe_boxed(mut f: Box<FnMut(Event) + 'a>) -> Self {
EventHandler {
run: Box::new(move |ev| {
f(ev);
HandlerResult::Continue
}),
}
}
#[inline]
pub fn run(&mut self, ev: Event) -> HandlerResult {
(self.run)(ev)
}
}
#[must_use]
......
use input::Event;
#[must_use]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum HandlerResult {
Continue,
QuitLoop,
}
// TODO: Consider making this a trait, or a type alias for a raw FnMut
pub struct EventHandler<'a> {
run: Box<FnMut(Event) -> HandlerResult + 'a>,
}
impl<'a> EventHandler<'a> {
pub fn new<F>(f: F) -> Self
where F: FnMut(Event) -> HandlerResult + 'a
{
EventHandler { run: Box::new(f) }
}
pub fn new_boxed(f: Box<FnMut(Event) -> HandlerResult + 'a>) -> Self {
EventHandler { run: f }
}
pub fn new_safe<F>(mut f: F) -> Self
where F: FnMut(Event) + 'a
{
EventHandler {
run: Box::new(move |ev| {
f(ev);
HandlerResult::Continue
}),
}
}
pub fn new_safe_boxed(mut f: Box<FnMut(Event) + 'a>) -> Self {
EventHandler {
run: Box::new(move |ev| {
f(ev);
HandlerResult::Continue
}),
}
}
#[inline]
pub fn run(&mut self, ev: Event) -> HandlerResult {
(self.run)(ev)
}
}
use input::Event;
pub fn user_command_reject_handler(_: Event) {}
struct SphinxHead;
use actors::{Actor, LockAction};
#[macro_use]
mod environment;
mod handlers;
mod states;
mod event_handler;
use std::time::Duration;
use crossbeam::scope;
use self::environment::*;
use self::event_handler::*;
use actors::Actor;
use input::Event;
use util::wakeable::SpawnWakeable;
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
enum LockAction {
PressLock,
PressUnlock,
Release,
}
struct Actors {
pub struct Actors {
green_led: Box<Actor<bool> + Send>,
lock_actor: Box<Actor<LockAction> + Send>,
}
trait State {
fn run(&mut self, &mut Actors, &mut Environment) -> Option<Box<State>>;
}
fn user_command_reject_handler(_: Event) {}
#[derive(Debug)]
pub struct UnLockingState {
locking: bool,
}
impl State for UnLockingState {
fn run(&mut self, actors: &mut Actors, env: &mut Environment) -> Option<Box<State>> {
// TODO: abort if already locked
let locking = self.locking;
for _ in 0..3 {
let lock_actor = &mut actors.lock_actor; // move out
let cancel = scope(|scope| {
// it is important that we keep this thread alife, so remember the return value
// TODO: Change the API around so that this pitfall no longer exists
scope.spawn_wakeable(move |t| {
lock_actor.act(if locking {
LockAction::PressLock
} else {
LockAction::PressUnlock
});
t.sleep(Duration::from_millis(100));
lock_actor.act(LockAction::Release);
});
let r = handle_events_timeout!(env,
Duration::from_secs(1),
EventHandler::new_safe(user_command_reject_handler),
EventHandler::new(|ev| {
match ev {
Event::DoorLocked(b) if b == locking => {
HandlerResult::QuitLoop
}
_ => HandlerResult::Continue,
}
}));
if r != EventsResult::Timeout {
assert!(r == EventsResult::ShuttingDown || env.door_locked() == locking);
return true;
}
return false;
});
if cancel {
break;
}
}
None
}
pub trait State {
fn run(&mut self, &mut Actors, &mut environment::Environment) -> Option<Box<State>>;
}
use std::time::Duration;
use crossbeam::scope;
use actors::{Actor, LockAction};
use input::Event;
use util::wakeable::SpawnWakeable;
use brain::environment::*;
use brain::handlers;
use brain::{Actors, State};
#[derive(Debug)]
pub struct UnLockingState {
locking: bool,
}
impl UnLockingState {
pub fn new(locking: bool) -> UnLockingState {
UnLockingState { locking: locking }
}
}
impl State for UnLockingState {
fn run(&mut self, actors: &mut Actors, env: &mut Environment) -> Option<Box<State>> {
// TODO: abort if already locked
let locking = self.locking;
for _ in 0..3 {
let lock_actor = &mut actors.lock_actor; // move out
let cancel = scope(|scope| {
// it is important that we keep this thread alife, so remember the return value
// TODO: Change the API around so that this pitfall no longer exists
scope.spawn_wakeable(move |t| {
lock_actor.act(if locking {
LockAction::PressLock
} else {
LockAction::PressUnlock
});
t.sleep(Duration::from_millis(100));
lock_actor.act(LockAction::Release);
});
let r = handle_events_timeout!(env,
Duration::from_secs(1),
EventHandler::new_safe(handlers::user_command_reject_handler),
EventHandler::new(|ev| {
match ev {
Event::DoorLocked(b) if b == locking => {
HandlerResult::QuitLoop
}
_ => HandlerResult::Continue,
}
}));
if r != EventsResult::Timeout {
assert!(r == EventsResult::ShuttingDown || env.door_locked() == locking);
return true;
}
return false;
});
if cancel {
break;
}
}
None
}
}
pub mod wakeable;
use std::time::Duration;
use std::thread;
use chan;
pub mod wakeable;
pub fn timeout_chan(d: Duration) -> chan::Receiver<()> {
let (s, r) = chan::sync(0);
thread::spawn(move || {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment