mirror of
https://github.com/yewstack/yew.git
synced 2026-02-01 17:26:28 +00:00
Remove slab from scheduler
This commit is contained in:
parent
51141e9202
commit
c5ca223d27
@ -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 }
|
||||
|
||||
23
src/html.rs
23
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<CTX>> 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<CTX, COMP: Component<CTX>> {
|
||||
index: Rc<RefCell<Option<RunnableIndex>>>,
|
||||
runnable: Shared<Option<Shared<BoxedRunnable<CTX>>>>,
|
||||
scheduler: Scheduler<CTX>,
|
||||
queue: Rc<RefCell<VecDeque<ComponentUpdate<CTX, COMP>>>>,
|
||||
queue: Shared<VecDeque<ComponentUpdate<CTX, COMP>>>,
|
||||
}
|
||||
|
||||
impl<CTX, COMP: Component<CTX>> Clone for Activator<CTX, COMP> {
|
||||
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<CTX, COMP: Component<CTX>> Activator<CTX, COMP> {
|
||||
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<CTX> + Renderable<CTX, COMP>,
|
||||
{
|
||||
pub(crate) fn new(scheduler: Scheduler<CTX>) -> 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<CTX>;
|
||||
let runnable = Rc::new(RefCell::new(runnable));
|
||||
*activator.runnable.borrow_mut() = Some(runnable);
|
||||
activator.send(ComponentUpdate::Create);
|
||||
activator
|
||||
}
|
||||
|
||||
@ -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")]
|
||||
|
||||
@ -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<CTX> {
|
||||
fn run<'a>(&mut self, context: &'a mut CTX) -> WillDestroy;
|
||||
}
|
||||
|
||||
/// The `Pool` which keep a sequence of runnables to start next.
|
||||
struct Pool<CTX> {
|
||||
slab: Slab<Rc<RefCell<BoxedRunnable<CTX>>>>,
|
||||
sequence: VecDeque<RunnableIndex>,
|
||||
}
|
||||
|
||||
impl<CTX> Pool<CTX> {
|
||||
/// Put a runnable and return a unique id.
|
||||
fn register(&mut self, runnable: BoxedRunnable<CTX>) -> RunnableIndex {
|
||||
let runnable = Rc::new(RefCell::new(runnable));
|
||||
self.slab.insert(runnable)
|
||||
}
|
||||
|
||||
fn unregister(&mut self, index: RunnableIndex) -> BoxedRunnable<CTX> {
|
||||
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<RefCell<BoxedRunnable<CTX>>>)> {
|
||||
self.sequence.pop_front().and_then(|idx| {
|
||||
self.slab.get(idx).cloned().map(|runnable| (idx, runnable))
|
||||
})
|
||||
}
|
||||
}
|
||||
pub(crate) type Shared<T> = Rc<RefCell<T>>;
|
||||
|
||||
/// This is a global scheduler suitable to schedule and run any tasks.
|
||||
pub struct Scheduler<CTX> {
|
||||
context: Rc<RefCell<CTX>>,
|
||||
pool: Rc<RefCell<Pool<CTX>>>,
|
||||
context: Shared<CTX>,
|
||||
sequence: Shared<VecDeque<Shared<BoxedRunnable<CTX>>>>,
|
||||
}
|
||||
|
||||
impl<CTX> Clone for Scheduler<CTX> {
|
||||
fn clone(&self) -> Self {
|
||||
Scheduler {
|
||||
context: self.context.clone(),
|
||||
pool: self.pool.clone(),
|
||||
sequence: self.sequence.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,53 +36,25 @@ impl<CTX> Clone for Scheduler<CTX> {
|
||||
impl<CTX> Scheduler<CTX> {
|
||||
/// 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<T>(&mut self, runnable: T) -> RunnableIndex
|
||||
where
|
||||
T: Runnable<CTX> + 'static,
|
||||
{
|
||||
let runnable: BoxedRunnable<CTX> = 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<BoxedRunnable<CTX>>) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user