[−][src]Struct juggle::Wheel
Single-thread async task scheduler with dynamic task state control. Implements Future
.
This structure is useful when you want to divide single thread to share processing power among multiple task by cooperative multitasking.
Tasks are scheduled using round-robin algorithm without priority. Diagram below shows simplified scheduling process.
Execute
|
+--v--+ +-----+-----+-----+-----+
| | | | | | <---+
| 0x0 | <-- | 0x8 | 0x9 | 0xA | 0xB | |
| | | | | | <-+ |
+-----+ ... +-----+-----+-----+-----+ | |
| | |
| | |
+---v---+ | |
/ \ YES | |
+ Runnable? +----------------------------+ |
\ / |
+-------+ |
| NO +-----------------------+ |
+---------> Wait for waking event |--+
+-----------------------+
New and rescheduled tasks are added at the end of queue. Task on front is poped and executed. If task finishes or becomes cancelled then it is removed from scheduler, and if task is suspended then it is also removed but only from queue not the scheduler. Tasks that were blocked by some async event are checked periodically and when woken they are added at the end of queue, this might not happen immedialty after task is woken.
Managing tasks
You can spawn/suspend/resume/cancel any task as long as you have its identifier, and
handle to this scheduler. Handle can be obtained from this
object using that method, and task identifiers are returned from
functions that spawn tasks (e.g spawn
).
Be carefull tho with suspending tasks, if all become suspended then because of scheduler
single-thread nature there is no way of resuming any. Such condition triggers
SuspendError
that is returned from future.
Examples
use juggle::*; use alloc::collections::VecDeque; use core::cell::RefCell; async fn collect_temperature(queue: &RefCell<VecDeque<i32>>,handle: WheelHandle<'_>){ loop{ // loop forever or until cancelled let temperature: i32 = read_temperature_sensor().await; queue.borrow_mut().push_back(temperature); yield_once!(); // give scheduler opportunity to execute other tasks } } async fn wait_for_timer(id: IdNum,queue: &RefCell<VecDeque<i32>>,handle: WheelHandle<'_>){ init_timer(); for _ in 0..5 { yield_while!(get_timer_value() < 200); // busy wait but also executes other tasks. process_data(&mut queue.borrow_mut()); reset_timer(); } handle.cancel(id); // cancel 'collect_temperature' task. shutdown_timer(); } fn main(){ let queue = &RefCell::new(VecDeque::new()); let wheel = Wheel::new(); let handle = wheel.handle(); // handle to manage tasks, can be cloned inside this thread let temp_id = handle.spawn(SpawnParams::default(), collect_temperature(queue,handle.clone())); handle.spawn(SpawnParams::default(), wait_for_timer(temp_id.unwrap(),queue,handle.clone())); // execute tasks smol::block_on(wheel).unwrap(); // or any other utility to block on future. }
Implementations
impl<'futures> Wheel<'futures>
[src]
pub fn new() -> Self
[src]
Create new instance
pub fn handle(&self) -> &WheelHandle<'futures>
[src]
Obtain reference to handle that is used to spawn/control tasks.
Any interaction with Wheel
's content is done by handles. Handles works as reference
counted pointers, they can be cloned to use inside tasks but cannot be shared
between threads.
pub fn lock(self) -> LockedWheel<'futures>ⓘNotable traits for LockedWheel<'futures>
impl<'futures> Future for LockedWheel<'futures> type Output = Result<(), SuspendError>;
[src]
Notable traits for LockedWheel<'futures>
impl<'futures> Future for LockedWheel<'futures> type Output = Result<(), SuspendError>;
Lock this wheel preventing all handles from affecting the tasks.
Transforms this instance into LockedWheel
which is similar to
Wheel
but has no way of controlling tasks within it.
Panics
Panics if this method was called inside handle's method such as
with_name
.
Trait Implementations
impl<'futures> Debug for Wheel<'futures>
[src]
impl<'futures> Default for Wheel<'futures>
[src]
impl<'futures> Future for Wheel<'futures>
[src]
Auto Trait Implementations
impl<'futures> !RefUnwindSafe for Wheel<'futures>
impl<'futures> !Send for Wheel<'futures>
impl<'futures> !Sync for Wheel<'futures>
impl<'futures> Unpin for Wheel<'futures>
impl<'futures> !UnwindSafe for Wheel<'futures>
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<F> IntoFuture for F where
F: Future,
[src]
F: Future,
type Output = <F as Future>::Output
into_future
)The output that the future will produce on completion.
type Future = F
into_future
)Which kind of future are we turning this into?
fn into_future(self) -> <F as IntoFuture>::Future
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,