mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-19 00:00:09 +02:00
tokio: remove needless generic type on LinkedList (#8188)
This commit is contained in:
@@ -20,7 +20,7 @@ pub(super) struct Synced {
|
||||
is_shutdown: bool,
|
||||
|
||||
// List of all registrations tracked by the set
|
||||
registrations: LinkedList<Arc<ScheduledIo>, ScheduledIo>,
|
||||
registrations: LinkedList<Arc<ScheduledIo>>,
|
||||
|
||||
// Registrations that are pending drop. When a `Registration` is dropped, it
|
||||
// stores its `ScheduledIo` in this list. The I/O driver is responsible for
|
||||
|
||||
@@ -107,12 +107,10 @@ pub(crate) struct ScheduledIo {
|
||||
waiters: Mutex<Waiters>,
|
||||
}
|
||||
|
||||
type WaitList = LinkedList<Waiter, <Waiter as linked_list::Link>::Target>;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Waiters {
|
||||
/// List of all current waiters.
|
||||
list: WaitList,
|
||||
list: LinkedList<Waiter>,
|
||||
|
||||
/// Waker used for `AsyncRead`.
|
||||
reader: Option<Waker>,
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
use crate::future::Future;
|
||||
use crate::loom::cell::UnsafeCell;
|
||||
use crate::runtime::task::{JoinHandle, LocalNotified, Notified, Schedule, SpawnLocation, Task};
|
||||
use crate::util::linked_list::{Link, LinkedList};
|
||||
use crate::util::sharded_list;
|
||||
use crate::util::linked_list::LinkedList;
|
||||
use crate::util::sharded_list::ShardedList;
|
||||
|
||||
use crate::loom::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::marker::PhantomData;
|
||||
@@ -56,13 +56,11 @@ cfg_not_has_atomic_u64! {
|
||||
}
|
||||
|
||||
pub(crate) struct OwnedTasks<S: 'static> {
|
||||
list: List<S>,
|
||||
list: ShardedList<Task<S>>,
|
||||
pub(crate) id: NonZeroU64,
|
||||
closed: AtomicBool,
|
||||
}
|
||||
|
||||
type List<S> = sharded_list::ShardedList<Task<S>, <Task<S> as Link>::Target>;
|
||||
|
||||
pub(crate) struct LocalOwnedTasks<S: 'static> {
|
||||
inner: UnsafeCell<OwnedTasksInner<S>>,
|
||||
pub(crate) id: NonZeroU64,
|
||||
@@ -70,7 +68,7 @@ pub(crate) struct LocalOwnedTasks<S: 'static> {
|
||||
}
|
||||
|
||||
struct OwnedTasksInner<S: 'static> {
|
||||
list: LinkedList<Task<S>, <Task<S> as Link>::Target>,
|
||||
list: LinkedList<Task<S>>,
|
||||
closed: bool,
|
||||
}
|
||||
|
||||
@@ -78,7 +76,7 @@ impl<S: 'static> OwnedTasks<S> {
|
||||
pub(crate) fn new(num_cores: usize) -> Self {
|
||||
let shard_size = Self::gen_shared_list_size(num_cores);
|
||||
Self {
|
||||
list: List::new(shard_size),
|
||||
list: ShardedList::new(shard_size),
|
||||
closed: AtomicBool::new(false),
|
||||
id: get_next_id(),
|
||||
}
|
||||
|
||||
@@ -322,8 +322,6 @@ pub(crate) struct TimerHandle {
|
||||
inner: NonNull<TimerShared>,
|
||||
}
|
||||
|
||||
pub(super) type EntryList = crate::util::linked_list::LinkedList<TimerShared, TimerShared>;
|
||||
|
||||
/// The shared state structure of a timer. This structure is shared between the
|
||||
/// frontend (`Entry`) and driver backend.
|
||||
///
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
mod entry;
|
||||
pub(crate) use entry::TimerEntry;
|
||||
use entry::{EntryList, TimerHandle, TimerShared, MAX_SAFE_MILLIS_DURATION};
|
||||
use entry::{TimerHandle, TimerShared, MAX_SAFE_MILLIS_DURATION};
|
||||
|
||||
mod handle;
|
||||
pub(crate) use self::handle::Handle;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::runtime::time::{EntryList, TimerHandle, TimerShared};
|
||||
use crate::runtime::time::{TimerHandle, TimerShared};
|
||||
use crate::util::linked_list::LinkedList;
|
||||
|
||||
use std::{array, fmt, ptr::NonNull};
|
||||
|
||||
@@ -16,7 +17,7 @@ pub(crate) struct Level {
|
||||
occupied: u64,
|
||||
|
||||
/// Slots. We access these via the EntryInner `current_list` as well, so this needs to be an `UnsafeCell`.
|
||||
slot: [EntryList; LEVEL_MULT],
|
||||
slot: [LinkedList<TimerShared>; LEVEL_MULT],
|
||||
}
|
||||
|
||||
/// Indicates when a slot must be processed next.
|
||||
@@ -42,7 +43,7 @@ impl Level {
|
||||
Level {
|
||||
level,
|
||||
occupied: 0,
|
||||
slot: array::from_fn(|_| EntryList::default()),
|
||||
slot: array::from_fn(|_| LinkedList::default()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +141,7 @@ impl Level {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn take_slot(&mut self, slot: usize) -> EntryList {
|
||||
pub(crate) fn take_slot(&mut self, slot: usize) -> LinkedList<TimerShared> {
|
||||
self.occupied &= !occupied_bit(slot);
|
||||
|
||||
std::mem::take(&mut self.slot[slot])
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::runtime::time::{TimerHandle, TimerShared};
|
||||
use crate::time::error::InsertError;
|
||||
use crate::util::linked_list::LinkedList;
|
||||
|
||||
mod level;
|
||||
pub(crate) use self::level::Expiration;
|
||||
@@ -8,7 +9,6 @@ use self::level::Level;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::entry::STATE_DEREGISTERED;
|
||||
use super::EntryList;
|
||||
|
||||
/// Timing wheel implementation.
|
||||
///
|
||||
@@ -36,7 +36,7 @@ pub(crate) struct Wheel {
|
||||
levels: Box<[Level; NUM_LEVELS]>,
|
||||
|
||||
/// Entries queued for firing
|
||||
pending: EntryList,
|
||||
pending: LinkedList<TimerShared>,
|
||||
}
|
||||
|
||||
/// Number of levels. Each level has 64 slots. By using 6 levels with 64 slots
|
||||
@@ -54,7 +54,7 @@ impl Wheel {
|
||||
Wheel {
|
||||
elapsed: 0,
|
||||
levels: levels.try_into().unwrap(),
|
||||
pending: EntryList::new(),
|
||||
pending: LinkedList::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ impl Wheel {
|
||||
}
|
||||
|
||||
/// Obtains the list of entries that need processing for the given expiration.
|
||||
fn take_entries(&mut self, expiration: &Expiration) -> EntryList {
|
||||
fn take_entries(&mut self, expiration: &Expiration) -> LinkedList<TimerShared> {
|
||||
self.levels[expiration.level].take_slot(expiration.slot)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use super::{CancellationQueueEntry, Entry, EntryHandle};
|
||||
use super::{CancellationQueueEntry, EntryHandle};
|
||||
use crate::loom::sync::{Arc, Mutex};
|
||||
use crate::util::linked_list;
|
||||
|
||||
type EntryList = linked_list::LinkedList<CancellationQueueEntry, Entry>;
|
||||
use crate::util::linked_list::LinkedList;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Inner {
|
||||
list: EntryList,
|
||||
list: LinkedList<CancellationQueueEntry>,
|
||||
}
|
||||
|
||||
impl Drop for Inner {
|
||||
@@ -21,7 +19,7 @@ impl Drop for Inner {
|
||||
impl Inner {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
list: EntryList::new(),
|
||||
list: LinkedList::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ use std::marker::PhantomPinned;
|
||||
use std::ptr::NonNull;
|
||||
use std::task::{Context, Poll, Waker};
|
||||
|
||||
pub(super) type EntryList = linked_list::LinkedList<Entry, Entry>;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct State {
|
||||
cancelled: bool,
|
||||
|
||||
@@ -5,8 +5,7 @@ pub(crate) mod cancellation_queue;
|
||||
|
||||
mod entry;
|
||||
pub(crate) use entry::Handle as EntryHandle;
|
||||
use entry::{CancellationQueueEntry, RegistrationQueueEntry, WakeQueueEntry};
|
||||
use entry::{Entry, EntryList};
|
||||
use entry::{CancellationQueueEntry, Entry, RegistrationQueueEntry, WakeQueueEntry};
|
||||
|
||||
mod registration_queue;
|
||||
pub(crate) use registration_queue::RegistrationQueue;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use super::{Entry, EntryHandle, RegistrationQueueEntry};
|
||||
use crate::util::linked_list;
|
||||
|
||||
type EntryList = linked_list::LinkedList<RegistrationQueueEntry, Entry>;
|
||||
use super::{EntryHandle, RegistrationQueueEntry};
|
||||
use crate::util::linked_list::LinkedList;
|
||||
|
||||
/// A queue of entries that need to be registered in the timer wheel.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RegistrationQueue {
|
||||
list: EntryList,
|
||||
list: LinkedList<RegistrationQueueEntry>,
|
||||
}
|
||||
|
||||
impl Drop for RegistrationQueue {
|
||||
@@ -21,7 +19,7 @@ impl Drop for RegistrationQueue {
|
||||
impl RegistrationQueue {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
list: EntryList::new(),
|
||||
list: LinkedList::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +27,7 @@ impl RegistrationQueue {
|
||||
///
|
||||
/// Behavior is undefined if any of the following conditions are violated:
|
||||
///
|
||||
/// - [`Entry::extra_pointers`] of `hdl` must not being used.
|
||||
/// - `Entry::extra_pointers` of `hdl` must not being used.
|
||||
pub(crate) unsafe fn push_front(&mut self, hdl: EntryHandle) {
|
||||
self.list.push_front(hdl);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use super::{Entry, EntryHandle, WakeQueueEntry};
|
||||
use crate::util::linked_list;
|
||||
|
||||
type EntryList = linked_list::LinkedList<WakeQueueEntry, Entry>;
|
||||
use super::{EntryHandle, WakeQueueEntry};
|
||||
use crate::util::linked_list::LinkedList;
|
||||
|
||||
/// A queue of entries that need to be woken up.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct WakeQueue {
|
||||
list: EntryList,
|
||||
list: LinkedList<WakeQueueEntry>,
|
||||
}
|
||||
|
||||
impl Drop for WakeQueue {
|
||||
@@ -21,7 +19,7 @@ impl Drop for WakeQueue {
|
||||
impl WakeQueue {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
list: EntryList::new(),
|
||||
list: LinkedList::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +31,7 @@ impl WakeQueue {
|
||||
///
|
||||
/// Behavior is undefined if any of the following conditions are violated:
|
||||
///
|
||||
/// - [`Entry::extra_pointers`] of `hdl` must not being used.
|
||||
/// - `Entry::extra_pointers` of `hdl` must not being used.
|
||||
pub(crate) unsafe fn push_front(&mut self, hdl: EntryHandle) {
|
||||
self.list.push_front(hdl);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::{EntryHandle, EntryList};
|
||||
use crate::util::linked_list::LinkedList;
|
||||
|
||||
use super::{Entry, EntryHandle};
|
||||
use std::ptr::NonNull;
|
||||
use std::{array, fmt};
|
||||
|
||||
@@ -16,7 +18,7 @@ pub(crate) struct Level {
|
||||
occupied: u64,
|
||||
|
||||
/// Slots. We access these via the EntryInner `current_list` as well, so this needs to be an `UnsafeCell`.
|
||||
slot: [EntryList; LEVEL_MULT],
|
||||
slot: [LinkedList<Entry>; LEVEL_MULT],
|
||||
}
|
||||
|
||||
/// Indicates when a slot must be processed next.
|
||||
@@ -42,7 +44,7 @@ impl Level {
|
||||
Level {
|
||||
level,
|
||||
occupied: 0,
|
||||
slot: array::from_fn(|_| EntryList::default()),
|
||||
slot: array::from_fn(|_| LinkedList::default()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +144,7 @@ impl Level {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn take_slot(&mut self, slot: usize) -> EntryList {
|
||||
pub(crate) fn take_slot(&mut self, slot: usize) -> LinkedList<Entry> {
|
||||
self.occupied &= !occupied_bit(slot);
|
||||
|
||||
std::mem::take(&mut self.slot[slot])
|
||||
|
||||
@@ -3,7 +3,9 @@ pub(crate) use self::level::Expiration;
|
||||
use self::level::Level;
|
||||
|
||||
use super::cancellation_queue::Sender;
|
||||
use super::{EntryHandle, EntryList, WakeQueue};
|
||||
use super::{Entry, EntryHandle, WakeQueue};
|
||||
|
||||
use crate::util::linked_list::LinkedList;
|
||||
|
||||
/// Hashed timing wheel implementation.
|
||||
///
|
||||
@@ -202,7 +204,7 @@ impl Wheel {
|
||||
}
|
||||
|
||||
/// Obtains the list of entries that need processing for the given expiration.
|
||||
fn take_entries(&mut self, expiration: &Expiration) -> EntryList {
|
||||
fn take_entries(&mut self, expiration: &Expiration) -> LinkedList<Entry> {
|
||||
self.levels[expiration.level].take_slot(expiration.slot)
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ pub(crate) struct Semaphore {
|
||||
}
|
||||
|
||||
struct Waitlist {
|
||||
queue: LinkedList<Waiter, <Waiter as linked_list::Link>::Target>,
|
||||
queue: LinkedList<Waiter>,
|
||||
closed: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ struct Tail {
|
||||
closed: bool,
|
||||
|
||||
/// Receivers waiting for a value.
|
||||
waiters: LinkedList<Waiter, <Waiter as linked_list::Link>::Target>,
|
||||
waiters: LinkedList<Waiter>,
|
||||
}
|
||||
|
||||
/// Slot in the buffer.
|
||||
@@ -943,7 +943,7 @@ fn new_receiver<T>(shared: Arc<Shared<T>>) -> Receiver<T> {
|
||||
/// and gates the access to it on the `Shared.tail` mutex. It also empties
|
||||
/// the list on drop.
|
||||
struct WaitersList<'a, T> {
|
||||
list: GuardedLinkedList<Waiter, <Waiter as linked_list::Link>::Target>,
|
||||
list: GuardedLinkedList<Waiter>,
|
||||
is_empty: bool,
|
||||
shared: &'a Shared<T>,
|
||||
}
|
||||
@@ -961,7 +961,7 @@ impl<'a, T> Drop for WaitersList<'a, T> {
|
||||
|
||||
impl<'a, T> WaitersList<'a, T> {
|
||||
fn new(
|
||||
unguarded_list: LinkedList<Waiter, <Waiter as linked_list::Link>::Target>,
|
||||
unguarded_list: LinkedList<Waiter>,
|
||||
guard: Pin<&'a Waiter>,
|
||||
shared: &'a Shared<T>,
|
||||
) -> Self {
|
||||
|
||||
@@ -20,9 +20,6 @@ use std::sync::atomic::Ordering::{self, Acquire, Relaxed, Release, SeqCst};
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll, Waker};
|
||||
|
||||
type WaitList = LinkedList<Waiter, <Waiter as linked_list::Link>::Target>;
|
||||
type GuardedWaitList = GuardedLinkedList<Waiter, <Waiter as linked_list::Link>::Target>;
|
||||
|
||||
/// Notifies a single task to wake up.
|
||||
///
|
||||
/// `Notify` provides a basic mechanism to notify a single task of an event.
|
||||
@@ -211,7 +208,7 @@ pub struct Notify {
|
||||
// - number of times `notify_waiters` was called can
|
||||
// be modified only if `waiters` lock is held
|
||||
state: AtomicUsize,
|
||||
waiters: Mutex<WaitList>,
|
||||
waiters: Mutex<LinkedList<Waiter>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -327,14 +324,14 @@ enum Notification {
|
||||
/// and gates the access to it on `notify.waiters` mutex. It also empties
|
||||
/// the list on drop.
|
||||
struct NotifyWaitersList<'a> {
|
||||
list: GuardedWaitList,
|
||||
list: GuardedLinkedList<Waiter>,
|
||||
is_empty: bool,
|
||||
notify: &'a Notify,
|
||||
}
|
||||
|
||||
impl<'a> NotifyWaitersList<'a> {
|
||||
fn new(
|
||||
unguarded_list: WaitList,
|
||||
unguarded_list: LinkedList<Waiter>,
|
||||
guard: Pin<&'a Waiter>,
|
||||
notify: &'a Notify,
|
||||
) -> NotifyWaitersList<'a> {
|
||||
@@ -349,7 +346,7 @@ impl<'a> NotifyWaitersList<'a> {
|
||||
|
||||
/// Removes the last element from the guarded list. Modifying this list
|
||||
/// requires an exclusive access to the main list in `Notify`.
|
||||
fn pop_back_locked(&mut self, _waiters: &mut WaitList) -> Option<NonNull<Waiter>> {
|
||||
fn pop_back_locked(&mut self, _waiters: &mut LinkedList<Waiter>) -> Option<NonNull<Waiter>> {
|
||||
let result = self.list.pop_back();
|
||||
if result.is_none() {
|
||||
// Save information about emptiness to avoid waiting for lock
|
||||
@@ -747,7 +744,7 @@ impl Notify {
|
||||
fn inner_notify_waiters<'a>(
|
||||
&'a self,
|
||||
curr: usize,
|
||||
mut waiters: crate::loom::sync::MutexGuard<'a, LinkedList<Waiter, Waiter>>,
|
||||
mut waiters: crate::loom::sync::MutexGuard<'a, LinkedList<Waiter>>,
|
||||
) {
|
||||
if matches!(get_state(curr), EMPTY | NOTIFIED) {
|
||||
// There are no waiting tasks. All we need to do is increment the
|
||||
@@ -842,7 +839,7 @@ impl UnwindSafe for Notify {}
|
||||
impl RefUnwindSafe for Notify {}
|
||||
|
||||
fn notify_locked(
|
||||
waiters: &mut WaitList,
|
||||
waiters: &mut LinkedList<Waiter>,
|
||||
state: &AtomicUsize,
|
||||
curr: usize,
|
||||
strategy: NotifyOneStrategy,
|
||||
@@ -1403,7 +1400,7 @@ fn is_unpin<T: Unpin>() {}
|
||||
/// While this guard is held, the `Notify` instance's waiter list is locked.
|
||||
pub(crate) struct NotifyGuard<'a> {
|
||||
guarded_notify: &'a Notify,
|
||||
guarded_waiters: crate::loom::sync::MutexGuard<'a, WaitList>,
|
||||
guarded_waiters: crate::loom::sync::MutexGuard<'a, LinkedList<Waiter>>,
|
||||
current_state: usize,
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,9 @@ use std::task::{Context, Waker};
|
||||
|
||||
use crate::loom::cell::UnsafeCell;
|
||||
use crate::loom::sync::{Arc, Mutex};
|
||||
use crate::util::linked_list::{self, Link};
|
||||
use crate::util::linked_list::{self, Link, LinkedList};
|
||||
use crate::util::{waker_ref, Wake};
|
||||
|
||||
type LinkedList<T> =
|
||||
linked_list::LinkedList<ListEntry<T>, <ListEntry<T> as linked_list::Link>::Target>;
|
||||
|
||||
/// This is the main handle to the collection.
|
||||
pub(crate) struct IdleNotifiedSet<T> {
|
||||
lists: Arc<Lists<T>>,
|
||||
@@ -47,8 +44,8 @@ type Lists<T> = Mutex<ListsInner<T>>;
|
||||
/// the destructor of the `IdleNotifiedSet` will clear the two lists, so once
|
||||
/// that object is destroyed, no ref-cycles will remain.
|
||||
struct ListsInner<T> {
|
||||
notified: LinkedList<T>,
|
||||
idle: LinkedList<T>,
|
||||
notified: LinkedList<ListEntry<T>>,
|
||||
idle: LinkedList<ListEntry<T>>,
|
||||
/// Whenever an element in the `notified` list is woken, this waker will be
|
||||
/// notified and consumed, if it exists.
|
||||
waker: Option<Waker>,
|
||||
@@ -233,7 +230,7 @@ impl<T> IdleNotifiedSet<T> {
|
||||
|
||||
/// Call a function on every element in this list.
|
||||
pub(crate) fn for_each<F: FnMut(&mut T)>(&mut self, mut func: F) {
|
||||
fn get_ptrs<T>(list: &mut LinkedList<T>, ptrs: &mut Vec<*mut T>) {
|
||||
fn get_ptrs<T>(list: &mut LinkedList<ListEntry<T>>, ptrs: &mut Vec<*mut T>) {
|
||||
let mut node = list.last();
|
||||
|
||||
while let Some(entry) = node {
|
||||
@@ -291,7 +288,7 @@ impl<T> IdleNotifiedSet<T> {
|
||||
// has `my_list` set to `Neither` and that the value has not yet been
|
||||
// dropped.
|
||||
struct AllEntries<T, F: FnMut(T)> {
|
||||
all_entries: LinkedList<T>,
|
||||
all_entries: LinkedList<ListEntry<T>>,
|
||||
func: F,
|
||||
}
|
||||
|
||||
@@ -346,7 +343,10 @@ impl<T> IdleNotifiedSet<T> {
|
||||
///
|
||||
/// The mutex for the entries must be held, and the target list must be such
|
||||
/// that setting `my_list` to `Neither` is ok.
|
||||
unsafe fn move_to_new_list<T>(from: &mut LinkedList<T>, to: &mut LinkedList<T>) {
|
||||
unsafe fn move_to_new_list<T>(
|
||||
from: &mut LinkedList<ListEntry<T>>,
|
||||
to: &mut LinkedList<ListEntry<T>>,
|
||||
) {
|
||||
while let Some(entry) = from.pop_back() {
|
||||
entry.my_list.with_mut(|ptr| {
|
||||
// Safety: pointer is accessed while holding the mutex.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
use core::cell::UnsafeCell;
|
||||
use core::fmt;
|
||||
use core::marker::{PhantomData, PhantomPinned};
|
||||
use core::marker::PhantomPinned;
|
||||
use core::mem::ManuallyDrop;
|
||||
use core::ptr::{self, NonNull};
|
||||
|
||||
@@ -23,19 +23,16 @@ use core::ptr::{self, NonNull};
|
||||
///
|
||||
/// Currently, the list is not emptied on drop. It is the caller's
|
||||
/// responsibility to ensure the list is empty before dropping it.
|
||||
pub(crate) struct LinkedList<L, T> {
|
||||
pub(crate) struct LinkedList<L: Link> {
|
||||
/// Linked list head
|
||||
head: Option<NonNull<T>>,
|
||||
head: Option<NonNull<L::Target>>,
|
||||
|
||||
/// Linked list tail
|
||||
tail: Option<NonNull<T>>,
|
||||
|
||||
/// Node type marker.
|
||||
_marker: PhantomData<*const L>,
|
||||
tail: Option<NonNull<L::Target>>,
|
||||
}
|
||||
|
||||
unsafe impl<L: Link> Send for LinkedList<L, L::Target> where L::Target: Send {}
|
||||
unsafe impl<L: Link> Sync for LinkedList<L, L::Target> where L::Target: Sync {}
|
||||
unsafe impl<L: Link> Send for LinkedList<L> where L::Target: Send {}
|
||||
unsafe impl<L: Link> Sync for LinkedList<L> where L::Target: Sync {}
|
||||
|
||||
/// Defines how a type is tracked within a linked list.
|
||||
///
|
||||
@@ -57,7 +54,6 @@ pub(crate) unsafe trait Link {
|
||||
type Target;
|
||||
|
||||
/// Convert the handle to a raw pointer without consuming the handle.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn as_raw(handle: &Self::Handle) -> NonNull<Self::Target>;
|
||||
|
||||
/// Convert the raw pointer to a handle
|
||||
@@ -112,18 +108,15 @@ unsafe impl<T: Sync> Sync for Pointers<T> {}
|
||||
|
||||
// ===== impl LinkedList =====
|
||||
|
||||
impl<L, T> LinkedList<L, T> {
|
||||
impl<L: Link> LinkedList<L> {
|
||||
/// Creates an empty linked list.
|
||||
pub(crate) const fn new() -> LinkedList<L, T> {
|
||||
pub(crate) const fn new() -> LinkedList<L> {
|
||||
LinkedList {
|
||||
head: None,
|
||||
tail: None,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: Link> LinkedList<L, L::Target> {
|
||||
/// Adds an element first in the list.
|
||||
pub(crate) fn push_front(&mut self, val: L::Handle) {
|
||||
// The value should not be dropped, it is being inserted into the list
|
||||
@@ -241,7 +234,7 @@ impl<L: Link> LinkedList<L, L::Target> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: Link> fmt::Debug for LinkedList<L, L::Target> {
|
||||
impl<L: Link> fmt::Debug for LinkedList<L> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("LinkedList")
|
||||
.field("head", &self.head)
|
||||
@@ -257,14 +250,14 @@ impl<L: Link> fmt::Debug for LinkedList<L, L::Target> {
|
||||
feature = "signal",
|
||||
feature = "sync",
|
||||
))]
|
||||
impl<L: Link> LinkedList<L, L::Target> {
|
||||
impl<L: Link> LinkedList<L> {
|
||||
pub(crate) fn last(&self) -> Option<&L::Target> {
|
||||
let tail = self.tail.as_ref()?;
|
||||
unsafe { Some(&*tail.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: Link> Default for LinkedList<L, L::Target> {
|
||||
impl<L: Link> Default for LinkedList<L> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
@@ -273,16 +266,16 @@ impl<L: Link> Default for LinkedList<L, L::Target> {
|
||||
// ===== impl DrainFilter =====
|
||||
|
||||
cfg_io_driver_impl! {
|
||||
pub(crate) struct DrainFilter<'a, T: Link, F> {
|
||||
list: &'a mut LinkedList<T, T::Target>,
|
||||
pub(crate) struct DrainFilter<'a, L: Link, F> {
|
||||
list: &'a mut LinkedList<L>,
|
||||
filter: F,
|
||||
curr: Option<NonNull<T::Target>>,
|
||||
curr: Option<NonNull<L::Target>>,
|
||||
}
|
||||
|
||||
impl<T: Link> LinkedList<T, T::Target> {
|
||||
pub(crate) fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F>
|
||||
impl<L: Link> LinkedList<L> {
|
||||
pub(crate) fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, L, F>
|
||||
where
|
||||
F: FnMut(&T::Target) -> bool,
|
||||
F: FnMut(&L::Target) -> bool,
|
||||
{
|
||||
let curr = self.head;
|
||||
DrainFilter {
|
||||
@@ -293,17 +286,16 @@ cfg_io_driver_impl! {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, F> Iterator for DrainFilter<'a, T, F>
|
||||
impl<'a, L: Link, F> Iterator for DrainFilter<'a, L, F>
|
||||
where
|
||||
T: Link,
|
||||
F: FnMut(&T::Target) -> bool,
|
||||
F: FnMut(&L::Target) -> bool,
|
||||
{
|
||||
type Item = T::Handle;
|
||||
type Item = L::Handle;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(curr) = self.curr {
|
||||
// safety: the pointer references data contained by the list
|
||||
self.curr = unsafe { T::pointers(curr).as_ref() }.get_next();
|
||||
self.curr = unsafe { L::pointers(curr).as_ref() }.get_next();
|
||||
|
||||
// safety: the value is still owned by the linked list.
|
||||
if (self.filter)(unsafe { &mut *curr.as_ptr() }) {
|
||||
@@ -317,18 +309,18 @@ cfg_io_driver_impl! {
|
||||
}
|
||||
|
||||
cfg_taskdump! {
|
||||
impl<T: Link> LinkedList<T, T::Target> {
|
||||
impl<L: Link> LinkedList<L> {
|
||||
pub(crate) fn for_each<F>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&T::Handle),
|
||||
F: FnMut(&L::Handle),
|
||||
{
|
||||
let mut next = self.head;
|
||||
|
||||
while let Some(curr) = next {
|
||||
unsafe {
|
||||
let handle = ManuallyDrop::new(T::from_raw(curr));
|
||||
let handle = ManuallyDrop::new(L::from_raw(curr));
|
||||
f(&handle);
|
||||
next = T::pointers(curr).as_ref().get_next();
|
||||
next = L::pointers(curr).as_ref().get_next();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,19 +344,16 @@ feature! {
|
||||
///
|
||||
/// If a list is empty, then both pointers of the guard node are pointing
|
||||
/// at the guard node itself.
|
||||
pub(crate) struct GuardedLinkedList<L, T> {
|
||||
pub(crate) struct GuardedLinkedList<L: Link> {
|
||||
/// Pointer to the guard node.
|
||||
guard: NonNull<T>,
|
||||
|
||||
/// Node type marker.
|
||||
_marker: PhantomData<*const L>,
|
||||
guard: NonNull<L::Target>,
|
||||
}
|
||||
|
||||
impl<L: Link> LinkedList<L, L::Target> {
|
||||
impl<L: Link> LinkedList<L> {
|
||||
/// Turns a linked list into the guarded version by linking the guard node
|
||||
/// with the head and tail nodes. Like with other nodes, you should guarantee
|
||||
/// that the guard node is pinned in memory.
|
||||
pub(crate) fn into_guarded(self, guard_handle: L::Handle) -> GuardedLinkedList<L, L::Target> {
|
||||
pub(crate) fn into_guarded(self, guard_handle: L::Handle) -> GuardedLinkedList<L> {
|
||||
// `guard_handle` is a NonNull pointer, we don't have to care about dropping it.
|
||||
let guard = L::as_raw(&guard_handle);
|
||||
|
||||
@@ -386,11 +375,11 @@ feature! {
|
||||
}
|
||||
}
|
||||
|
||||
GuardedLinkedList { guard, _marker: PhantomData }
|
||||
GuardedLinkedList { guard }
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: Link> GuardedLinkedList<L, L::Target> {
|
||||
impl<L: Link> GuardedLinkedList<L> {
|
||||
fn tail(&self) -> Option<NonNull<L::Target>> {
|
||||
let tail_ptr = unsafe {
|
||||
L::pointers(self.guard).as_ref().get_prev().unwrap()
|
||||
@@ -515,7 +504,7 @@ pub(crate) mod tests {
|
||||
r.as_ref().get_ref().into()
|
||||
}
|
||||
|
||||
fn collect_list(list: &mut LinkedList<&'_ Entry, <&'_ Entry as Link>::Target>) -> Vec<i32> {
|
||||
fn collect_list(list: &mut LinkedList<&'_ Entry>) -> Vec<i32> {
|
||||
let mut ret = vec![];
|
||||
|
||||
while let Some(entry) = list.pop_back() {
|
||||
@@ -525,10 +514,7 @@ pub(crate) mod tests {
|
||||
ret
|
||||
}
|
||||
|
||||
fn push_all<'a>(
|
||||
list: &mut LinkedList<&'a Entry, <&'_ Entry as Link>::Target>,
|
||||
entries: &[Pin<&'a Entry>],
|
||||
) {
|
||||
fn push_all<'a>(list: &mut LinkedList<&'a Entry>, entries: &[Pin<&'a Entry>]) {
|
||||
for entry in entries.iter() {
|
||||
list.push_front(*entry);
|
||||
}
|
||||
@@ -552,7 +538,7 @@ pub(crate) mod tests {
|
||||
|
||||
#[test]
|
||||
fn const_new() {
|
||||
const _: LinkedList<&Entry, <&Entry as Link>::Target> = LinkedList::new();
|
||||
const _: LinkedList<&Entry> = LinkedList::new();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -580,7 +566,7 @@ pub(crate) mod tests {
|
||||
let a = entry(5);
|
||||
let b = entry(7);
|
||||
|
||||
let mut list = LinkedList::<&Entry, <&Entry as Link>::Target>::new();
|
||||
let mut list = LinkedList::<&Entry>::new();
|
||||
|
||||
list.push_front(a.as_ref());
|
||||
|
||||
@@ -737,7 +723,7 @@ pub(crate) mod tests {
|
||||
|
||||
unsafe {
|
||||
// Remove missing
|
||||
let mut list = LinkedList::<&Entry, <&Entry as Link>::Target>::new();
|
||||
let mut list = LinkedList::<&Entry>::new();
|
||||
|
||||
list.push_front(b.as_ref());
|
||||
list.push_front(a.as_ref());
|
||||
@@ -766,7 +752,7 @@ pub(crate) mod tests {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut ll = LinkedList::<&Entry, <&Entry as Link>::Target>::new();
|
||||
let mut ll = LinkedList::<&Entry>::new();
|
||||
let mut reference = VecDeque::new();
|
||||
|
||||
let entries: Vec<_> = (0..ops.len()).map(|i| entry(i as i32)).collect();
|
||||
|
||||
@@ -12,8 +12,8 @@ use super::linked_list::{Link, LinkedList};
|
||||
/// responsibility to ensure the list is empty before dropping it.
|
||||
///
|
||||
/// Note: Due to its inner sharded design, the order of nodes cannot be guaranteed.
|
||||
pub(crate) struct ShardedList<L, T> {
|
||||
lists: Box<[Mutex<LinkedList<L, T>>]>,
|
||||
pub(crate) struct ShardedList<L: ShardedListItem> {
|
||||
lists: Box<[Mutex<LinkedList<L>>]>,
|
||||
added: MetricAtomicU64,
|
||||
count: MetricAtomicUsize,
|
||||
shard_mask: usize,
|
||||
@@ -32,7 +32,15 @@ pub(crate) unsafe trait ShardedListItem: Link {
|
||||
unsafe fn get_shard_id(target: NonNull<Self::Target>) -> usize;
|
||||
}
|
||||
|
||||
impl<L, T> ShardedList<L, T> {
|
||||
/// Used to get the lock of shard.
|
||||
pub(crate) struct ShardGuard<'a, L: Link> {
|
||||
lock: MutexGuard<'a, LinkedList<L>>,
|
||||
added: &'a MetricAtomicU64,
|
||||
count: &'a MetricAtomicUsize,
|
||||
id: usize,
|
||||
}
|
||||
|
||||
impl<L: ShardedListItem> ShardedList<L> {
|
||||
/// Creates a new and empty sharded linked list with the specified size.
|
||||
pub(crate) fn new(sharded_size: usize) -> Self {
|
||||
assert!(sharded_size.is_power_of_two());
|
||||
@@ -46,17 +54,7 @@ impl<L, T> ShardedList<L, T> {
|
||||
shard_mask,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to get the lock of shard.
|
||||
pub(crate) struct ShardGuard<'a, L, T> {
|
||||
lock: MutexGuard<'a, LinkedList<L, T>>,
|
||||
added: &'a MetricAtomicU64,
|
||||
count: &'a MetricAtomicUsize,
|
||||
id: usize,
|
||||
}
|
||||
|
||||
impl<L: ShardedListItem> ShardedList<L, L::Target> {
|
||||
/// Removes the last element from a list specified by `shard_id` and returns it, or None if it is
|
||||
/// empty.
|
||||
pub(crate) fn pop_back(&self, shard_id: usize) -> Option<L::Handle> {
|
||||
@@ -89,7 +87,7 @@ impl<L: ShardedListItem> ShardedList<L, L::Target> {
|
||||
}
|
||||
|
||||
/// Gets the lock of `ShardedList`, makes us have the write permission.
|
||||
pub(crate) fn lock_shard(&self, val: &L::Handle) -> ShardGuard<'_, L, L::Target> {
|
||||
pub(crate) fn lock_shard(&self, val: &L::Handle) -> ShardGuard<'_, L> {
|
||||
let id = unsafe { L::get_shard_id(L::as_raw(val)) };
|
||||
ShardGuard {
|
||||
lock: self.shard_inner(id),
|
||||
@@ -126,13 +124,13 @@ impl<L: ShardedListItem> ShardedList<L, L::Target> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shard_inner(&self, id: usize) -> MutexGuard<'_, LinkedList<L, <L as Link>::Target>> {
|
||||
fn shard_inner(&self, id: usize) -> MutexGuard<'_, LinkedList<L>> {
|
||||
// Safety: This modulo operation ensures that the index is not out of bounds.
|
||||
unsafe { self.lists.get_unchecked(id & self.shard_mask).lock() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, L: ShardedListItem> ShardGuard<'a, L, L::Target> {
|
||||
impl<'a, L: ShardedListItem> ShardGuard<'a, L> {
|
||||
/// Push a value to this shard.
|
||||
pub(crate) fn push(mut self, val: L::Handle) {
|
||||
let id = unsafe { L::get_shard_id(L::as_raw(&val)) };
|
||||
@@ -144,7 +142,7 @@ impl<'a, L: ShardedListItem> ShardGuard<'a, L, L::Target> {
|
||||
}
|
||||
|
||||
cfg_taskdump! {
|
||||
impl<L: ShardedListItem> ShardedList<L, L::Target> {
|
||||
impl<L: ShardedListItem> ShardedList<L> {
|
||||
pub(crate) fn for_each<F>(&self, mut f: F)
|
||||
where
|
||||
F: FnMut(&L::Handle),
|
||||
|
||||
Reference in New Issue
Block a user