use std::collections::HashMap;
use std::sync::Mutex;
use crate::scheduler::SpringId;
pub type ScopeId = u64;
static SCOPES: Mutex<Option<ScopeRegistry>> = Mutex::new(None);
struct ScopeRegistry {
spring_scopes: HashMap<ScopeId, Vec<SpringId>>,
active_scope: Option<ScopeId>,
next_id: u64,
}
impl ScopeRegistry {
fn new() -> Self {
Self {
spring_scopes: HashMap::new(),
active_scope: None,
next_id: 1,
}
}
}
fn with_registry<R>(f: impl FnOnce(&mut ScopeRegistry) -> R) -> R {
let mut guard = SCOPES.lock().unwrap();
let registry = guard.get_or_insert_with(ScopeRegistry::new);
f(registry)
}
pub fn create_scope() -> ScopeId {
with_registry(|r| {
let id = r.next_id;
r.next_id += 1;
r.spring_scopes.insert(id, Vec::new());
id
})
}
pub fn enter_scope(scope: ScopeId) {
with_registry(|r| {
r.active_scope = Some(scope);
});
}
pub fn exit_scope() {
with_registry(|r| {
r.active_scope = None;
});
}
pub fn current_scope() -> Option<ScopeId> {
with_registry(|r| r.active_scope)
}
pub fn register_spring(spring_id: SpringId) {
with_registry(|r| {
if let Some(scope) = r.active_scope {
r.spring_scopes.entry(scope).or_default().push(spring_id);
}
});
}
pub fn suspend_scope(scope: ScopeId, handle: &crate::SchedulerHandle) {
let springs = with_registry(|r| r.spring_scopes.get(&scope).cloned().unwrap_or_default());
for id in springs {
handle.pause_spring(id);
}
}
pub fn resume_scope(scope: ScopeId, handle: &crate::SchedulerHandle) {
let springs = with_registry(|r| r.spring_scopes.get(&scope).cloned().unwrap_or_default());
for id in springs {
handle.resume_spring(id);
}
}
pub fn remove_scope(scope: ScopeId) {
with_registry(|r| {
r.spring_scopes.remove(&scope);
});
}
pub fn unregister_spring(spring_id: SpringId) {
with_registry(|r| {
for springs in r.spring_scopes.values_mut() {
springs.retain(|&id| id != spring_id);
}
});
}