From c5ca223d279ccfa0e57fa3cf8695a2fe0e332ce4 Mon Sep 17 00:00:00 2001 From: Denis Kolodin Date: Sat, 12 May 2018 22:24:21 +0300 Subject: [PATCH] Remove slab from scheduler --- Cargo.toml | 1 - src/html.rs | 23 ++++++------- src/lib.rs | 1 - src/scheduler.rs | 85 +++++++----------------------------------------- 4 files changed, 24 insertions(+), 86 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 538a76c60..e807a519a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ http = "0.1" serde = "1" serde_json = "1" stdweb = "0.4" -slab = "0.4" toml = { version = "0.4", optional = true } serde_yaml = { version = "0.7", optional = true } rmp-serde = { version = "0.13.7", optional = true } diff --git a/src/html.rs b/src/html.rs index 79df958df..8763fbc63 100644 --- a/src/html.rs +++ b/src/html.rs @@ -12,7 +12,7 @@ use stdweb::web::{Element, EventListenerHandle, INode, Node}; use stdweb::web::html_element::SelectElement; use virtual_dom::{Listener, VDiff, VNode}; use callback::Callback; -use scheduler::{Scheduler, RunnableIndex, Runnable, WillDestroy}; +use scheduler::{Scheduler, Runnable, WillDestroy, Shared, BoxedRunnable}; /// This type indicates that component should be rendered again. pub type ShouldRender = bool; @@ -114,15 +114,15 @@ impl<'a, CTX: 'static, COMP: Component> Env<'a, CTX, COMP> { /// Holds a reference to a scope, could put a message into the queue /// of the scope and activate processing (try borrow and call routine). pub struct Activator> { - index: Rc>>, + runnable: Shared>>>, scheduler: Scheduler, - queue: Rc>>>, + queue: Shared>>, } impl> Clone for Activator { fn clone(&self) -> Self { Activator { - index: self.index.clone(), + runnable: self.runnable.clone(), scheduler: self.scheduler.clone(), queue: self.queue.clone(), } @@ -136,10 +136,10 @@ impl> Activator { self.queue.try_borrow_mut() .expect("internal message routing accident") .push_back(update); - let idx = self.index.borrow().as_ref() + let runnable = self.runnable.borrow().as_ref() .cloned() - .expect("index was not set"); - self.scheduler.put_and_try_run(idx); + .expect("runnable was not set"); + self.scheduler.put_and_try_run(runnable); } /// Send message to a component. @@ -169,9 +169,9 @@ where COMP: Component + Renderable, { pub(crate) fn new(scheduler: Scheduler) -> Self { - let index = Rc::new(RefCell::new(None)); + let runnable = Rc::new(RefCell::new(None)); let queue = Rc::new(RefCell::new(VecDeque::new())); - let env = Activator { index, scheduler, queue }; + let env = Activator { runnable, scheduler, queue }; Scope { env } } @@ -198,8 +198,9 @@ where init_props, }; let mut activator = self.env.clone(); - let idx = activator.scheduler.register(runnable); - *activator.index.borrow_mut() = Some(idx); + let runnable = Box::new(runnable) as BoxedRunnable; + let runnable = Rc::new(RefCell::new(runnable)); + *activator.runnable.borrow_mut() = Some(runnable); activator.send(ComponentUpdate::Create); activator } diff --git a/src/lib.rs b/src/lib.rs index f67971e2e..3e40c8ae8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,7 +57,6 @@ extern crate serde; extern crate serde_json; #[macro_use] extern crate stdweb; -extern crate slab; #[cfg(feature = "toml")] extern crate toml; #[cfg(feature = "yaml")] diff --git a/src/scheduler.rs b/src/scheduler.rs index c36fb2faf..74aefca15 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -3,10 +3,6 @@ use std::collections::VecDeque; use std::rc::Rc; use std::cell::RefCell; -use slab::Slab; - -/// Id of a runnable instance. -pub(crate) type RunnableIndex = usize; /// The flag that means the routine should be destroyed. pub(crate) type WillDestroy = bool; @@ -20,48 +16,19 @@ pub(crate) trait Runnable { fn run<'a>(&mut self, context: &'a mut CTX) -> WillDestroy; } -/// The `Pool` which keep a sequence of runnables to start next. -struct Pool { - slab: Slab>>>, - sequence: VecDeque, -} - -impl Pool { - /// Put a runnable and return a unique id. - fn register(&mut self, runnable: BoxedRunnable) -> RunnableIndex { - let runnable = Rc::new(RefCell::new(runnable)); - self.slab.insert(runnable) - } - - fn unregister(&mut self, index: RunnableIndex) -> BoxedRunnable { - let runnable = self.slab.remove(index); - Rc::try_unwrap(runnable).ok() - .expect("runnable was locked") - .into_inner() - } - - fn put(&mut self, index: RunnableIndex) { - self.sequence.push_back(index); - } - - fn next(&mut self) -> Option<(RunnableIndex, Rc>>)> { - self.sequence.pop_front().and_then(|idx| { - self.slab.get(idx).cloned().map(|runnable| (idx, runnable)) - }) - } -} +pub(crate) type Shared = Rc>; /// This is a global scheduler suitable to schedule and run any tasks. pub struct Scheduler { - context: Rc>, - pool: Rc>>, + context: Shared, + sequence: Shared>>>, } impl Clone for Scheduler { fn clone(&self) -> Self { Scheduler { context: self.context.clone(), - pool: self.pool.clone(), + sequence: self.sequence.clone(), } } } @@ -69,53 +36,25 @@ impl Clone for Scheduler { impl Scheduler { /// Creates a new scheduler with a context. pub fn new(context: CTX) -> Self { - let pool = Pool { - slab: Slab::new(), - sequence: VecDeque::new(), - }; + let sequence = VecDeque::new(); Scheduler { context: Rc::new(RefCell::new(context)), - pool: Rc::new(RefCell::new(pool)), + sequence: Rc::new(RefCell::new(sequence)), } } - pub(crate) fn register(&mut self, runnable: T) -> RunnableIndex - where - T: Runnable + 'static, - { - let runnable: BoxedRunnable = Box::new(runnable); - self.pool.try_borrow_mut() - .expect("can't borrow slab to register a runnable") - .register(runnable) - } - - pub(crate) fn put_and_try_run(&mut self, index: RunnableIndex) { - self.pool.borrow_mut().put(index); - // Context lock also means the loop is runnging - let mut unreg = Vec::new(); + pub(crate) fn put_and_try_run(&mut self, runnable: Shared>) { + self.sequence.borrow_mut().push_back(runnable); + // Context lock also means the loop is running if let Ok(ref mut context) = self.context.try_borrow_mut() { loop { - let do_next = self.pool.borrow_mut().next(); - if let Some((idx, routine)) = do_next { - let will_destroy = routine.borrow_mut().run(context); - if will_destroy { - // TODO Filter deque (remove items with this id) - // because they must not be called and after - // the routine removed new call won't added with this id - // even if callback still exists - unreg.push(idx); - } + let do_next = self.sequence.borrow_mut().pop_front(); + if let Some(routine) = do_next { + routine.borrow_mut().run(context); } else { break; } } } - // Remove unnecessary routines only when loop finished completely, - // because they could call each other - for idx in unreg.into_iter() { - self.pool.try_borrow_mut() - .expect("can't borrow slab to unregister a runnable") - .unregister(idx); - } } }