extern crate alloc;
use alloc::vec::Vec;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
pub type TaskNumberType = usize;
#[cfg(not(feature = "c-library"))]
type TaskSetupFunctionType = fn() -> ();
#[cfg(feature = "c-library")]
type TaskSetupFunctionType = extern "C" fn() -> ();
#[cfg(not(feature = "c-library"))]
type TaskLoopFunctionType = fn() -> ();
#[cfg(feature = "c-library")]
type TaskLoopFunctionType = extern "C" fn() -> ();
#[cfg(not(feature = "c-library"))]
type TaskStopConditionFunctionType = fn() -> bool;
#[cfg(feature = "c-library")]
type TaskStopConditionFunctionType = extern "C" fn() -> bool;
#[repr(C)]
struct Task {
setup_fn: TaskSetupFunctionType,
loop_fn: TaskLoopFunctionType,
stop_condition_fn: TaskStopConditionFunctionType,
}
#[repr(C)]
struct FutureTask {
task: Task,
is_setup_completed: bool,
}
impl Future for FutureTask {
type Output = ();
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut array: [usize; 8] = core::array::from_fn(|i| i);
array[0] = 5;
if (self.task.stop_condition_fn)() {
Poll::Ready(())
} else {
if !self.is_setup_completed {
(self.task.setup_fn)();
self.is_setup_completed = true;
} else {
(self.task.loop_fn)();
}
Poll::Pending
}
}
}
fn task_waker() -> Waker {
fn raw_clone(_: *const ()) -> RawWaker {
RawWaker::new(core::ptr::null::<()>(), &NOOP_WAKER_VTABLE)
}
fn raw_wake(_: *const ()) {}
fn raw_wake_by_ref(_: *const ()) {}
fn raw_drop(_: *const ()) {}
static NOOP_WAKER_VTABLE: RawWakerVTable =
RawWakerVTable::new(raw_clone, raw_wake, raw_wake_by_ref, raw_drop);
let raw_waker = RawWaker::new(core::ptr::null::<()>(), &NOOP_WAKER_VTABLE);
unsafe { Waker::from_raw(raw_waker) }
}
#[repr(C)]
pub struct TaskManager {
tasks: Vec<FutureTask>,
task_to_execute_index: TaskNumberType,
}
static mut TASK_MANAGER: TaskManager = TaskManager::new();
impl TaskManager {
const fn new() -> TaskManager {
TaskManager {
tasks: Vec::new(),
task_to_execute_index: 0,
}
}
pub fn add_task(
setup_fn: TaskSetupFunctionType,
loop_fn: TaskLoopFunctionType,
stop_condition_fn: TaskStopConditionFunctionType,
) {
let task = Task {
setup_fn,
loop_fn,
stop_condition_fn,
};
let future_task = FutureTask {
task,
is_setup_completed: false,
};
unsafe {
TASK_MANAGER.tasks.push(future_task);
}
}
fn task_manager_step() {
if unsafe { !TASK_MANAGER.tasks.is_empty() } {
let waker = task_waker();
let task = unsafe { &mut TASK_MANAGER.tasks[TASK_MANAGER.task_to_execute_index] };
let mut task_future_pin = Pin::new(task);
let _ = task_future_pin
.as_mut()
.poll(&mut Context::from_waker(&waker));
unsafe {
if TASK_MANAGER.task_to_execute_index + 1 < TASK_MANAGER.tasks.len() {
TASK_MANAGER.task_to_execute_index += 1;
} else {
TASK_MANAGER.task_to_execute_index = 0;
}
}
}
}
pub fn start_task_manager() -> ! {
loop {
TaskManager::task_manager_step();
}
}
pub fn test_start_task_manager() {
for _n in 1..=1000 {
TaskManager::task_manager_step();
}
}
}