195 lines
5.1 KiB
Rust
195 lines
5.1 KiB
Rust
use crate::ScopeId;
|
|
use crate::Task;
|
|
use std::borrow::Borrow;
|
|
use std::cell::Cell;
|
|
use std::cell::RefCell;
|
|
use std::collections::BTreeSet;
|
|
use std::hash::Hash;
|
|
|
|
#[derive(Debug, Clone, Copy, Eq)]
|
|
pub struct ScopeOrder {
|
|
pub(crate) height: u32,
|
|
pub(crate) id: ScopeId,
|
|
}
|
|
|
|
impl ScopeOrder {
|
|
pub fn new(height: u32, id: ScopeId) -> Self {
|
|
Self { height, id }
|
|
}
|
|
}
|
|
|
|
impl PartialEq for ScopeOrder {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.id == other.id
|
|
}
|
|
}
|
|
|
|
impl PartialOrd for ScopeOrder {
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl Ord for ScopeOrder {
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
self.height.cmp(&other.height).then(self.id.cmp(&other.id))
|
|
}
|
|
}
|
|
|
|
impl Hash for ScopeOrder {
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
self.id.hash(state);
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct DirtyScopes {
|
|
pub(crate) scopes: BTreeSet<ScopeOrder>,
|
|
pub(crate) tasks: BTreeSet<DirtyTasks>,
|
|
}
|
|
|
|
impl DirtyScopes {
|
|
pub fn queue_task(&mut self, task: Task, order: ScopeOrder) {
|
|
match self.tasks.get(&order) {
|
|
Some(scope) => scope.queue_task(task),
|
|
None => {
|
|
let mut scope = DirtyTasks::from(order);
|
|
scope.queue_task(task);
|
|
self.tasks.insert(scope);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn queue_scope(&mut self, order: ScopeOrder) {
|
|
self.scopes.insert(order);
|
|
}
|
|
|
|
pub fn has_dirty_scopes(&self) -> bool {
|
|
!self.scopes.is_empty()
|
|
}
|
|
|
|
pub fn pop_task(&mut self) -> Option<DirtyTasks> {
|
|
self.tasks.pop_first()
|
|
}
|
|
|
|
pub fn pop_scope(&mut self) -> Option<ScopeOrder> {
|
|
self.scopes.pop_first()
|
|
}
|
|
|
|
pub fn pop_work(&mut self) -> Option<Work> {
|
|
let dirty_scope = self.scopes.first();
|
|
let dirty_task = self.tasks.first();
|
|
match (dirty_scope, dirty_task) {
|
|
(Some(scope), Some(task)) => {
|
|
let tasks_order = task.borrow();
|
|
match scope.cmp(tasks_order) {
|
|
std::cmp::Ordering::Less => {
|
|
let scope = self.scopes.pop_first().unwrap();
|
|
Some(Work {
|
|
scope: scope,
|
|
rerun_scope: true,
|
|
tasks: Vec::new(),
|
|
})
|
|
}
|
|
std::cmp::Ordering::Greater => {
|
|
let task = self.tasks.pop_first().unwrap();
|
|
Some(Work {
|
|
scope: task.order,
|
|
rerun_scope: false,
|
|
tasks: task.tasks_queued.into_inner(),
|
|
})
|
|
}
|
|
std::cmp::Ordering::Equal => {
|
|
let scope = self.scopes.pop_first().unwrap();
|
|
let task = self.tasks.pop_first().unwrap();
|
|
Some(Work {
|
|
scope: scope,
|
|
rerun_scope: true,
|
|
tasks: task.tasks_queued.into_inner(),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
(Some(scope), None) => {
|
|
let scope = self.scopes.pop_first().unwrap();
|
|
Some(Work {
|
|
scope: scope,
|
|
rerun_scope: true,
|
|
tasks: Vec::new(),
|
|
})
|
|
}
|
|
(None, Some(task)) => {
|
|
let task = self.tasks.pop_first().unwrap();
|
|
Some(Work {
|
|
scope: task.order,
|
|
rerun_scope: false,
|
|
tasks: task.tasks_queued.into_inner(),
|
|
})
|
|
}
|
|
(None, None) => None,
|
|
}
|
|
}
|
|
|
|
pub fn remove(&mut self, scope: &ScopeOrder) {
|
|
self.scopes.remove(scope);
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Work {
|
|
pub scope: ScopeOrder,
|
|
pub rerun_scope: bool,
|
|
pub tasks: Vec<Task>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Eq)]
|
|
pub(crate) struct DirtyTasks {
|
|
pub order: ScopeOrder,
|
|
pub tasks_queued: RefCell<Vec<Task>>,
|
|
}
|
|
|
|
impl From<ScopeOrder> for DirtyTasks {
|
|
fn from(order: ScopeOrder) -> Self {
|
|
Self {
|
|
order,
|
|
tasks_queued: Vec::new().into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DirtyTasks {
|
|
pub fn queue_task(&self, task: Task) {
|
|
self.tasks_queued.borrow_mut().push(task);
|
|
}
|
|
}
|
|
|
|
impl Borrow<ScopeOrder> for DirtyTasks {
|
|
fn borrow(&self) -> &ScopeOrder {
|
|
&self.order
|
|
}
|
|
}
|
|
|
|
impl PartialOrd for DirtyTasks {
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
Some(self.order.cmp(&other.order))
|
|
}
|
|
}
|
|
|
|
impl Ord for DirtyTasks {
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
self.order.cmp(&other.order)
|
|
}
|
|
}
|
|
|
|
impl PartialEq for DirtyTasks {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.order == other.order
|
|
}
|
|
}
|
|
|
|
impl Hash for DirtyTasks {
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
self.order.hash(state);
|
|
}
|
|
}
|