use performables::arc::Arc;
use thread_aware::{Thread, ThreadAware};
use tick::Clock;
use crate::io::Io;
use crate::runtime::RuntimeControl;
use crate::runtime::dispatch::DispatcherClient;
use crate::task::scheduler::Scheduler;
#[derive(Debug, Clone)]
pub struct Context {
inner: Arc<ContextInner>,
}
#[derive(Debug, Clone)]
struct ContextInner {
scheduler: Scheduler,
control: RuntimeControl,
thread: Thread,
clock: Clock,
io: Io,
}
impl Context {
#[must_use]
#[inline]
pub fn scheduler(&self) -> &Scheduler {
&self.inner.scheduler
}
#[must_use]
#[inline]
pub fn control(&self) -> &RuntimeControl {
&self.inner.control
}
#[must_use]
#[inline]
pub fn thread(&self) -> &Thread {
&self.inner.thread
}
#[must_use]
#[inline]
pub fn clock(&self) -> &Clock {
&self.inner.clock
}
#[must_use]
#[inline]
pub fn io(&self) -> &Io {
&self.inner.io
}
}
impl ThreadAware for Context {
fn relocate(&mut self, _source: Option<&Thread>, destination: &Thread) {
if self.inner.thread == *destination {
return;
}
let Some(worker_index) = self.inner.scheduler.resolve_worker_index(destination) else {
return;
};
let inner = Arc::make_mut(&mut self.inner);
let source = inner.thread.clone();
inner.scheduler.relocate_to_worker(destination, worker_index);
inner.thread = destination.clone();
inner.clock.relocate(Some(&source), destination);
inner.io.relocate(Some(&source), destination);
}
}
impl Context {
pub(crate) fn new(dispatcher: DispatcherClient, clock: Clock, io: Io, thread: Thread) -> Self {
Self {
inner: Arc::new(ContextInner {
scheduler: Scheduler::new(dispatcher.clone(), thread.clone()),
control: RuntimeControl::new(dispatcher),
thread,
clock,
io,
}),
}
}
pub(crate) fn dispatcher(&self) -> &DispatcherClient {
&self.inner.scheduler.dispatcher
}
}
impl AsRef<Scheduler> for Context {
#[inline]
fn as_ref(&self) -> &Scheduler {
self.scheduler()
}
}
impl AsRef<Clock> for Context {
#[inline]
fn as_ref(&self) -> &Clock {
self.clock()
}
}