aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Emil Fresk <emil.fresk@gmail.com> 2021-08-16 15:37:39 +0200
committerGravatar Emil Fresk <emil.fresk@gmail.com> 2021-08-16 15:38:31 +0200
commitbc3eb5c54784c32ccfff404dba58a27d5a47f04e (patch)
tree73d4d91075f06a35149ee3b5303bde465d881a64
parent74b396497861ad69dcab0414851ddb8b5c624036 (diff)
downloadrtic-bc3eb5c54784c32ccfff404dba58a27d5a47f04e.tar.gz
rtic-bc3eb5c54784c32ccfff404dba58a27d5a47f04e.tar.zst
rtic-bc3eb5c54784c32ccfff404dba58a27d5a47f04e.zip
Remove linked list impl - use heapless, linked list init now const fn
-rw-r--r--Cargo.toml2
-rw-r--r--macros/src/codegen/module.rs6
-rw-r--r--macros/src/codegen/pre_init.rs10
-rw-r--r--macros/src/codegen/timer_queue.rs13
-rw-r--r--src/export.rs1
-rw-r--r--src/lib.rs2
-rw-r--r--src/linked_list.rs597
-rw-r--r--src/tq.rs10
8 files changed, 16 insertions, 625 deletions
diff --git a/Cargo.toml b/Cargo.toml
index e3cb010b..ed0312df 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -44,7 +44,7 @@ cortex-m = "0.7.0"
cortex-m-rtic-macros = { path = "macros", version = "0.6.0-alpha.5" }
rtic-monotonic = "0.1.0-alpha.2"
rtic-core = "0.3.1"
-heapless = "0.7.1"
+heapless = "0.7.5"
bare-metal = "1.0.0"
[dependencies.dwt-systick-monotonic]
diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs
index c7092bd3..d3afb27b 100644
--- a/macros/src/codegen/module.rs
+++ b/macros/src/codegen/module.rs
@@ -327,7 +327,7 @@ pub fn codegen(
impl #internal_spawn_handle_ident {
pub fn cancel(self) -> Result<#ty, ()> {
rtic::export::interrupt::free(|_| unsafe {
- let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr();
+ let tq = #tq.get_mut_unchecked();
if let Some((_task, index)) = tq.cancel_marker(self.marker) {
// Get the message
let msg = #inputs
@@ -359,7 +359,7 @@ pub fn codegen(
let marker = *#tq_marker.get_mut_unchecked();
*#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1);
- let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr();
+ let tq = #tq.get_mut_unchecked();
tq.update_marker(self.marker, marker, instant, || #pend).map(|_| #name::#m::SpawnHandle { marker })
})
@@ -420,7 +420,7 @@ pub fn codegen(
*#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1);
- let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr();
+ let tq = #tq.get_mut_unchecked();
tq.enqueue_unchecked(
nr,
diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs
index ae628f6e..5b1fdf3e 100644
--- a/macros/src/codegen/pre_init.rs
+++ b/macros/src/codegen/pre_init.rs
@@ -77,18 +77,10 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
);));
}
- // Initialize monotonic's interrupts and timer queues
+ // Initialize monotonic's interrupts
for (_, monotonic) in &app.monotonics {
let priority = &monotonic.args.priority;
let binds = &monotonic.args.binds;
- let monotonic_name = monotonic.ident.to_string();
- let tq = util::tq_ident(&monotonic_name);
- let tq = util::mark_internal_ident(&tq);
-
- // Initialize timer queues
- stmts.push(
- quote!(#tq.get_mut_unchecked().as_mut_ptr().write(rtic::export::TimerQueue::new());),
- );
// Compile time assert that this priority is supported by the device
stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs
index abddbadc..bf896ee6 100644
--- a/macros/src/codegen/timer_queue.rs
+++ b/macros/src/codegen/timer_queue.rs
@@ -62,21 +62,20 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
{
// For future use
// let doc = &format!("Timer queue for {}", monotonic_name);
- let cap: u8 = app
+ let cap: usize = app
.software_tasks
.iter()
- .map(|(_name, task)| task.args.capacity)
+ .map(|(_name, task)| task.args.capacity as usize)
.sum();
- let n = util::capacity_literal(cap as usize);
- let tq_ty =
- quote!(core::mem::MaybeUninit<rtic::export::TimerQueue<#mono_type, #t, #n>>);
+ let n = util::capacity_literal(cap);
+ let tq_ty = quote!(rtic::export::TimerQueue<#mono_type, #t, #n>);
// For future use
// let doc = format!(" RTIC internal: {}:{}", file!(), line!());
items.push(quote!(
#[doc(hidden)]
static #tq: rtic::RacyCell<#tq_ty> =
- rtic::RacyCell::new(core::mem::MaybeUninit::uninit());
+ rtic::RacyCell::new(rtic::export::TimerQueue(rtic::export::SortedLinkedList::new_u16()));
));
let mono = util::monotonic_ident(&monotonic_name);
@@ -138,7 +137,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
unsafe fn #bound_interrupt() {
while let Some((task, index)) = rtic::export::interrupt::free(|_|
if let Some(mono) = #m_ident.get_mut_unchecked().as_mut() {
- (&mut *#tq.get_mut_unchecked().as_mut_ptr()).dequeue(|| #disable_isr, mono)
+ #tq.get_mut_unchecked().dequeue(|| #disable_isr, mono)
} else {
// We can only use the timer queue if `init` has returned, and it
// writes the `Some(monotonic)` we are accessing here.
diff --git a/src/export.rs b/src/export.rs
index e449ef41..927e951e 100644
--- a/src/export.rs
+++ b/src/export.rs
@@ -13,6 +13,7 @@ pub use cortex_m::{
peripheral::{scb::SystemHandler, syst::SystClkSource, DWT, NVIC},
Peripherals,
};
+pub use heapless::sorted_linked_list::SortedLinkedList;
pub use heapless::spsc::Queue;
pub use heapless::BinaryHeap;
pub use rtic_monotonic as monotonic;
diff --git a/src/lib.rs b/src/lib.rs
index cd511996..ca52ec1e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -43,8 +43,6 @@ pub use rtic_monotonic::{self, embedded_time as time, Monotonic};
#[doc(hidden)]
pub mod export;
#[doc(hidden)]
-mod linked_list;
-#[doc(hidden)]
mod tq;
/// Sets the given `interrupt` as pending
diff --git a/src/linked_list.rs b/src/linked_list.rs
deleted file mode 100644
index bbb935f8..00000000
--- a/src/linked_list.rs
+++ /dev/null
@@ -1,597 +0,0 @@
-use core::fmt;
-use core::marker::PhantomData;
-use core::mem::MaybeUninit;
-use core::ops::{Deref, DerefMut};
-use core::ptr;
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-struct LinkedIndex(u16);
-
-impl LinkedIndex {
- #[inline]
- const unsafe fn new_unchecked(value: u16) -> Self {
- LinkedIndex(value)
- }
-
- #[inline]
- const fn none() -> Self {
- LinkedIndex(u16::MAX)
- }
-
- #[inline]
- const fn option(self) -> Option<u16> {
- if self.0 == u16::MAX {
- None
- } else {
- Some(self.0)
- }
- }
-}
-
-/// A node in the linked list.
-pub struct Node<T> {
- val: MaybeUninit<T>,
- next: LinkedIndex,
-}
-
-/// Iterator for the linked list.
-pub struct Iter<'a, T, Kind, const N: usize>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- list: &'a LinkedList<T, Kind, N>,
- index: LinkedIndex,
-}
-
-impl<'a, T, Kind, const N: usize> Iterator for Iter<'a, T, Kind, N>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- type Item = &'a T;
-
- fn next(&mut self) -> Option<Self::Item> {
- let index = self.index.option()?;
-
- let node = self.list.node_at(index as usize);
- self.index = node.next;
-
- Some(self.list.read_data_in_node_at(index as usize))
- }
-}
-
-/// Comes from [`LinkedList::find_mut`].
-pub struct FindMut<'a, T, Kind, const N: usize>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- list: &'a mut LinkedList<T, Kind, N>,
- is_head: bool,
- prev_index: LinkedIndex,
- index: LinkedIndex,
- maybe_changed: bool,
-}
-
-impl<'a, T, Kind, const N: usize> FindMut<'a, T, Kind, N>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- fn pop_internal(&mut self) -> T {
- if self.is_head {
- // If it is the head element, we can do a normal pop
- unsafe { self.list.pop_unchecked() }
- } else {
- // Somewhere in the list
-
- // Re-point the previous index
- self.list.node_at_mut(self.prev_index.0 as usize).next =
- self.list.node_at_mut(self.index.0 as usize).next;
-
- // Release the index into the free queue
- self.list.node_at_mut(self.index.0 as usize).next = self.list.free;
- self.list.free = self.index;
-
- self.list.extract_data_in_node_at(self.index.0 as usize)
- }
- }
-
- /// This will pop the element from the list.
- ///
- /// Complexity is O(1).
- #[inline]
- pub fn pop(mut self) -> T {
- self.pop_internal()
- }
-
- /// This will resort the element into the correct position in the list in needed.
- /// Same as calling `drop`.
- ///
- /// Complexity is worst-case O(N).
- #[inline]
- pub fn finish(self) {
- drop(self)
- }
-}
-
-impl<T, Kind, const N: usize> Drop for FindMut<'_, T, Kind, N>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- fn drop(&mut self) {
- // Only resort the list if the element has changed
- if self.maybe_changed {
- let val = self.pop_internal();
- unsafe { self.list.push_unchecked(val) };
- }
- }
-}
-
-impl<T, Kind, const N: usize> Deref for FindMut<'_, T, Kind, N>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- self.list.read_data_in_node_at(self.index.0 as usize)
- }
-}
-
-impl<T, Kind, const N: usize> DerefMut for FindMut<'_, T, Kind, N>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- fn deref_mut(&mut self) -> &mut Self::Target {
- self.maybe_changed = true;
- self.list.read_mut_data_in_node_at(self.index.0 as usize)
- }
-}
-
-impl<T, Kind, const N: usize> fmt::Debug for FindMut<'_, T, Kind, N>
-where
- T: PartialEq + PartialOrd + core::fmt::Debug,
- Kind: kind::Kind,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("FindMut")
- .field("prev_index", &self.prev_index)
- .field("index", &self.index)
- .field(
- "prev_value",
- &self
- .list
- .read_data_in_node_at(self.prev_index.option().unwrap() as usize),
- )
- .field(
- "value",
- &self
- .list
- .read_data_in_node_at(self.index.option().unwrap() as usize),
- )
- .finish()
- }
-}
-
-/// The linked list.
-pub struct LinkedList<T, Kind, const N: usize>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- list: MaybeUninit<[Node<T>; N]>,
- head: LinkedIndex,
- free: LinkedIndex,
- _kind: PhantomData<Kind>,
-}
-
-impl<T, Kind, const N: usize> LinkedList<T, Kind, N>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- /// Internal helper to not do pointer arithmetic all over the place.
- #[inline]
- fn node_at(&self, index: usize) -> &Node<T> {
- // Safety: The entire `self.list` is initialized in `new`, which makes this safe.
- unsafe { &*(self.list.as_ptr() as *const Node<T>).add(index) }
- }
-
- /// Internal helper to not do pointer arithmetic all over the place.
- #[inline]
- fn node_at_mut(&mut self, index: usize) -> &mut Node<T> {
- // Safety: The entire `self.list` is initialized in `new`, which makes this safe.
- unsafe { &mut *(self.list.as_mut_ptr() as *mut Node<T>).add(index) }
- }
-
- /// Internal helper to not do pointer arithmetic all over the place.
- #[inline]
- fn write_data_in_node_at(&mut self, index: usize, data: T) {
- unsafe {
- self.node_at_mut(index).val.as_mut_ptr().write(data);
- }
- }
-
- /// Internal helper to not do pointer arithmetic all over the place.
- #[inline]
- fn read_data_in_node_at(&self, index: usize) -> &T {
- unsafe { &*self.node_at(index).val.as_ptr() }
- }
-
- /// Internal helper to not do pointer arithmetic all over the place.
- #[inline]
- fn read_mut_data_in_node_at(&mut self, index: usize) -> &mut T {
- unsafe { &mut *self.node_at_mut(index).val.as_mut_ptr() }
- }
-
- /// Internal helper to not do pointer arithmetic all over the place.
- #[inline]
- fn extract_data_in_node_at(&mut self, index: usize) -> T {
- unsafe { self.node_at(index).val.as_ptr().read() }
- }
-
- /// Internal helper to not do pointer arithmetic all over the place.
- /// Safety: This can overwrite existing allocated nodes if used improperly, meaning their
- /// `Drop` methods won't run.
- #[inline]
- unsafe fn write_node_at(&mut self, index: usize, node: Node<T>) {
- (self.list.as_mut_ptr() as *mut Node<T>)
- .add(index)
- .write(node)
- }
-
- /// Create a new linked list.
- pub fn new() -> Self {
- let mut list = LinkedList {
- list: MaybeUninit::uninit(),
- head: LinkedIndex::none(),
- free: unsafe { LinkedIndex::new_unchecked(0) },
- _kind: PhantomData,
- };
-
- let len = N as u16;
- let mut free = 0;
-
- if len == 0 {
- list.free = LinkedIndex::none();
- return list;
- }
-
- // Initialize indexes
- while free < len - 1 {
- unsafe {
- list.write_node_at(
- free as usize,
- Node {
- val: MaybeUninit::uninit(),
- next: LinkedIndex::new_unchecked(free + 1),
- },
- );
- }
- free += 1;
- }
-
- // Initialize final index
- unsafe {
- list.write_node_at(
- free as usize,
- Node {
- val: MaybeUninit::uninit(),
- next: LinkedIndex::none(),
- },
- );
- }
-
- list
- }
-
- /// Push unchecked
- ///
- /// Complexity is O(N).
- ///
- /// # Safety
- ///
- /// Assumes that the list is not full.
- pub unsafe fn push_unchecked(&mut self, value: T) {
- let new = self.free.0;
- // Store the data and update the next free spot
- self.write_data_in_node_at(new as usize, value);
- self.free = self.node_at(new as usize).next;
-
- if let Some(head) = self.head.option() {
- // Check if we need to replace head
- if self
- .read_data_in_node_at(head as usize)
- .partial_cmp(self.read_data_in_node_at(new as usize))
- != Kind::ordering()
- {
- self.node_at_mut(new as usize).next = self.head;
- self.head = LinkedIndex::new_unchecked(new);
- } else {
- // It's not head, search the list for the correct placement
- let mut current = head;
-
- while let Some(next) = self.node_at(current as usize).next.option() {
- if self
- .read_data_in_node_at(next as usize)
- .partial_cmp(self.read_data_in_node_at(new as usize))
- != Kind::ordering()
- {
- break;
- }
-
- current = next;
- }
-
- self.node_at_mut(new as usize).next = self.node_at(current as usize).next;
- self.node_at_mut(current as usize).next = LinkedIndex::new_unchecked(new);
- }
- } else {
- self.node_at_mut(new as usize).next = self.head;
- self.head = LinkedIndex::new_unchecked(new);
- }
- }
-
- /// Pushes an element to the linked list and sorts it into place.
- ///
- /// Complexity is O(N).
- pub fn push(&mut self, value: T) -> Result<(), T> {
- if !self.is_full() {
- Ok(unsafe { self.push_unchecked(value) })
- } else {
- Err(value)
- }
- }
-
- /// Get an iterator over the sorted list.
- pub fn iter(&self) -> Iter<'_, T, Kind, N> {
- Iter {
- list: self,
- index: self.head,
- }
- }
-
- /// Find an element in the list.
- pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMut<'_, T, Kind, N>>
- where
- F: FnMut(&T) -> bool,
- {
- let head = self.head.option()?;
-
- // Special-case, first element
- if f(self.read_data_in_node_at(head as usize)) {
- return Some(FindMut {
- is_head: true,
- prev_index: LinkedIndex::none(),
- index: self.head,
- list: self,
- maybe_changed: false,
- });
- }
-
- let mut current = head;
-
- while let Some(next) = self.node_at(current as usize).next.option() {
- if f(self.read_data_in_node_at(next as usize)) {
- return Some(FindMut {
- is_head: false,
- prev_index: unsafe { LinkedIndex::new_unchecked(current) },
- index: unsafe { LinkedIndex::new_unchecked(next) },
- list: self,
- maybe_changed: false,
- });
- }
-
- current = next;
- }
-
- None
- }
-
- /// Peek at the first element.
- pub fn peek(&self) -> Option<&T> {
- self.head
- .option()
- .map(|head| self.read_data_in_node_at(head as usize))
- }
-
- /// Pop unchecked
- ///
- /// # Safety
- ///
- /// Assumes that the list is not empty.
- pub unsafe fn pop_unchecked(&mut self) -> T {
- let head = self.head.0;
- let current = head;
- self.head = self.node_at(head as usize).next;
- self.node_at_mut(current as usize).next = self.free;
- self.free = LinkedIndex::new_unchecked(current);
-
- self.extract_data_in_node_at(current as usize)
- }
-
- /// Pops the first element in the list.
- ///
- /// Complexity is O(1).
- pub fn pop(&mut self) -> Result<T, ()> {
- if !self.is_empty() {
- Ok(unsafe { self.pop_unchecked() })
- } else {
- Err(())
- }
- }
-
- /// Checks if the linked list is full.
- #[inline]
- pub fn is_full(&self) -> bool {
- self.free.option().is_none()
- }
-
- /// Checks if the linked list is empty.
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.head.option().is_none()
- }
-}
-
-impl<T, Kind, const N: usize> Drop for LinkedList<T, Kind, N>
-where
- T: PartialEq + PartialOrd,
- Kind: kind::Kind,
-{
- fn drop(&mut self) {
- let mut index = self.head;
-
- while let Some(i) = index.option() {
- let node = self.node_at_mut(i as usize);
- index = node.next;
-
- unsafe {
- ptr::drop_in_place(node.val.as_mut_ptr());
- }
- }
- }
-}
-
-impl<T, Kind, const N: usize> fmt::Debug for LinkedList<T, Kind, N>
-where
- T: PartialEq + PartialOrd + core::fmt::Debug,
- Kind: kind::Kind,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.iter()).finish()
- }
-}
-
-/// Min sorted linked list.
-pub struct Min;
-
-/// Max sorted linked list.
-pub struct Max;
-
-/// Sealed traits and implementations for `linked_list`
-pub mod kind {
- use super::{Max, Min};
- use core::cmp::Ordering;
-
- /// The linked list kind: min first or max first
- pub unsafe trait Kind {
- #[doc(hidden)]
- fn ordering() -> Option<Ordering>;
- }
-
- unsafe impl Kind for Min {
- #[inline]
- fn ordering() -> Option<Ordering> {
- Some(Ordering::Less)
- }
- }
-
- unsafe impl Kind for Max {
- #[inline]
- fn ordering() -> Option<Ordering> {
- Some(Ordering::Greater)
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- // Note this useful idiom: importing names from outer (for mod tests) scope.
- use super::*;
-
- #[test]
- fn test_peek() {
- let mut ll: LinkedList<u32, Max, 3> = LinkedList::new();
-
- ll.push(1).unwrap();
- assert_eq!(ll.peek().unwrap(), &1);
-
- ll.push(2).unwrap();
- assert_eq!(ll.peek().unwrap(), &2);
-
- ll.push(3).unwrap();
- assert_eq!(ll.peek().unwrap(), &3);
-
- let mut ll: LinkedList<u32, Min, 3> = LinkedList::new();
-
- ll.push(2).unwrap();
- assert_eq!(ll.peek().unwrap(), &2);
-
- ll.push(1).unwrap();
- assert_eq!(ll.peek().unwrap(), &1);
-
- ll.push(3).unwrap();
- assert_eq!(ll.peek().unwrap(), &1);
- }
-
- #[test]
- fn test_full() {
- let mut ll: LinkedList<u32, Max, 3> = LinkedList::new();
- ll.push(1).unwrap();
- ll.push(2).unwrap();
- ll.push(3).unwrap();
-
- assert!(ll.is_full())
- }
-
- #[test]
- fn test_empty() {
- let ll: LinkedList<u32, Max, 3> = LinkedList::new();
-
- assert!(ll.is_empty())
- }
-
- #[test]
- fn test_zero_size() {
- let ll: LinkedList<u32, Max, 0> = LinkedList::new();
-
- assert!(ll.is_empty());
- assert!(ll.is_full());
- }
-
- #[test]
- fn test_rejected_push() {
- let mut ll: LinkedList<u32, Max, 3> = LinkedList::new();
- ll.push(1).unwrap();
- ll.push(2).unwrap();
- ll.push(3).unwrap();
-
- // This won't fit
- let r = ll.push(4);
-
- assert_eq!(r, Err(4));
- }
-
- #[test]
- fn test_updating() {
- let mut ll: LinkedList<u32, Max, 3> = LinkedList::new();
- ll.push(1).unwrap();
- ll.push(2).unwrap();
- ll.push(3).unwrap();
-
- let mut find = ll.find_mut(|v| *v == 2).unwrap();
-
- *find += 1000;
- find.finish();
-
- assert_eq!(ll.peek().unwrap(), &1002);
-
- let mut find = ll.find_mut(|v| *v == 3).unwrap();
-
- *find += 1000;
- find.finish();
-
- assert_eq!(ll.peek().unwrap(), &1003);
-
- // Remove largest element
- ll.find_mut(|v| *v == 1003).unwrap().pop();
-
- assert_eq!(ll.peek().unwrap(), &1002);
- }
-}
diff --git a/src/tq.rs b/src/tq.rs
index cd44abe2..dcaccc9e 100644
--- a/src/tq.rs
+++ b/src/tq.rs
@@ -1,9 +1,9 @@
use crate::{
- linked_list::{LinkedList, Min},
time::{Clock, Instant},
Monotonic,
};
use core::cmp::Ordering;
+use heapless::sorted_linked_list::{LinkedIndexU16, Min, SortedLinkedList};
#[inline(always)]
fn unwrapper<T, E>(val: Result<T, E>) -> T {
@@ -14,7 +14,9 @@ fn unwrapper<T, E>(val: Result<T, E>) -> T {
}
}
-pub struct TimerQueue<Mono, Task, const N: usize>(pub LinkedList<NotReady<Mono, Task>, Min, N>)
+pub struct TimerQueue<Mono, Task, const N: usize>(
+ pub SortedLinkedList<NotReady<Mono, Task>, LinkedIndexU16, Min, N>,
+)
where
Mono: Monotonic,
Task: Copy;
@@ -24,10 +26,6 @@ where
Mono: Monotonic,
Task: Copy,
{
- pub fn new() -> Self {
- TimerQueue(LinkedList::new())
- }
-
/// # Safety
///
/// Writing to memory with a transmute in order to enable