From ea8eadf2c63dd97a7b6d7fc33401076e55ceba56 Mon Sep 17 00:00:00 2001 From: li_junsong Date: Tue, 27 Jun 2023 17:24:15 +0800 Subject: [PATCH] =?UTF-8?q?time=E6=A8=A1=E5=9D=97=E9=80=82=E9=85=8Dlinked?= =?UTF-8?q?=5Flist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: li_junsong --- ylong_runtime/src/time/driver.rs | 19 +++---- ylong_runtime/src/time/mod.rs | 28 +++++++--- ylong_runtime/src/time/sleep.rs | 5 +- ylong_runtime/src/time/timer_handle.rs | 29 ---------- ylong_runtime/src/time/wheel.rs | 73 +++++++++++++------------- 5 files changed, 69 insertions(+), 85 deletions(-) delete mode 100644 ylong_runtime/src/time/timer_handle.rs diff --git a/ylong_runtime/src/time/driver.rs b/ylong_runtime/src/time/driver.rs index c3c8b5b..03bc616 100644 --- a/ylong_runtime/src/time/driver.rs +++ b/ylong_runtime/src/time/driver.rs @@ -11,11 +11,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::time::timer_handle::TimerHandle; use crate::time::wheel::Wheel; +use crate::time::Clock; use std::convert::TryInto; use std::fmt::Error; use std::mem::MaybeUninit; +use std::ptr::NonNull; use std::sync::{Mutex, Once}; use std::task::Waker; use std::time::Instant; @@ -47,9 +48,9 @@ impl Driver { self.start_time } - pub(crate) fn insert(&self, timer_handle: TimerHandle) -> Result { + pub(crate) fn insert(&self, clock_entry: NonNull) -> Result { let mut lock = self.wheel.lock().unwrap(); - lock.insert(timer_handle) + lock.insert(clock_entry) } pub(crate) fn run(&self) { @@ -66,17 +67,17 @@ impl Driver { let mut lock = self.wheel.lock().unwrap(); - while let Some(timer_handle) = lock.poll(now) { + while let Some(mut clock_entry) = lock.poll(now) { let elapsed = lock.elapsed(); lock.set_last_elapsed(elapsed); - // Unsafe access to timer_handle is only unsafe when Sleep Drop, - // but does not let `Sleep` go to `Ready` before access to timer_handle fetched by poll. - let timer_handle = unsafe { timer_handle.inner().as_mut() }; - waker_list[waker_idx] = timer_handle.take_waker(); + // Unsafe access to clock_entry is only unsafe when Sleep Drop, + // but does not let `Sleep` go to `Ready` before access to clock_entry fetched by poll. + let clock_handle = unsafe { clock_entry.as_mut() }; + waker_list[waker_idx] = clock_handle.take_waker(); waker_idx += 1; - timer_handle.set_result(true); + clock_handle.set_result(true); if waker_idx == waker_list.len() { for waker in waker_list.iter_mut() { diff --git a/ylong_runtime/src/time/mod.rs b/ylong_runtime/src/time/mod.rs index 3ea27d8..620c20f 100644 --- a/ylong_runtime/src/time/mod.rs +++ b/ylong_runtime/src/time/mod.rs @@ -18,7 +18,6 @@ mod error; mod sleep; mod timeout; mod timer; -mod timer_handle; mod wheel; pub(crate) use driver::Driver; @@ -26,8 +25,8 @@ pub use sleep::{sleep, sleep_until}; pub use timeout::timeout; pub use timer::{periodic_schedule, timer, timer_at, Timer}; -use crate::time::timer_handle::TimerHandle; -use std::ptr::NonNull; +use crate::util::link_list::{Link, Node}; +use std::ptr::{addr_of_mut, NonNull}; use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering::Relaxed; use std::task::Waker; @@ -50,6 +49,9 @@ pub(crate) struct Clock { // Corresponding waker, // which is used to wake up sleep coroutine. waker: Option, + + // Linked_list node. + node: Node, } impl Clock { @@ -61,6 +63,7 @@ impl Clock { duration: 0, result: AtomicBool::new(false), waker: None, + node: Node::new(), } } @@ -111,11 +114,20 @@ impl Clock { pub(crate) fn set_result(&mut self, result: bool) { self.result.store(result, Relaxed); } +} - // Creates a TimerHandle to point to the current structure. - pub(crate) fn handle(&self) -> TimerHandle { - TimerHandle { - inner: NonNull::from(self), - } +impl Default for Clock { + fn default() -> Self { + Clock::new() + } +} + +unsafe impl Link for Clock { + unsafe fn node(mut ptr: NonNull) -> NonNull> + where + Self: Sized, + { + let node_ptr = addr_of_mut!(ptr.as_mut().node); + NonNull::new_unchecked(node_ptr) } } diff --git a/ylong_runtime/src/time/sleep.rs b/ylong_runtime/src/time/sleep.rs index 57d2348..51031c3 100644 --- a/ylong_runtime/src/time/sleep.rs +++ b/ylong_runtime/src/time/sleep.rs @@ -16,6 +16,7 @@ use crate::time::Driver; use std::convert::TryInto; use std::future::Future; use std::pin::Pin; +use std::ptr::NonNull; use std::task::{Context, Poll}; use std::time::{Duration, Instant}; @@ -95,7 +96,7 @@ impl Sleep { fn cancel(&mut self) { let driver = Driver::get_ref(); let mut lock = driver.wheel.lock().unwrap(); - lock.cancel(&self.timer.handle()); + lock.cancel(NonNull::from(&self.timer)); } } @@ -115,7 +116,7 @@ impl Future for Sleep { self.timer.set_expiration(ms); self.timer.set_waker(cx.waker().clone()); - match driver.insert(self.timer.handle()) { + match driver.insert(NonNull::from(&self.timer)) { Ok(_) => self.need_insert = false, Err(_) => { // Even if the insertion fails, there is no need to insert again here, diff --git a/ylong_runtime/src/time/timer_handle.rs b/ylong_runtime/src/time/timer_handle.rs deleted file mode 100644 index e7d2c33..0000000 --- a/ylong_runtime/src/time/timer_handle.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2023 Huawei Device Co., Ltd. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::time::Clock; -use std::ptr::NonNull; - -// Pointer structure to Timer to circumvent lifecycle issues caused by references. -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] -pub(crate) struct TimerHandle { - pub(crate) inner: NonNull, -} - -impl TimerHandle { - // Return inner, - // which is a non_null pointer to Timer. - pub(crate) fn inner(&self) -> NonNull { - self.inner - } -} diff --git a/ylong_runtime/src/time/wheel.rs b/ylong_runtime/src/time/wheel.rs index 6f814c1..2657d9e 100644 --- a/ylong_runtime/src/time/wheel.rs +++ b/ylong_runtime/src/time/wheel.rs @@ -11,10 +11,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::time::timer_handle::TimerHandle; -use std::collections::VecDeque; +use crate::time::Clock; +use crate::util::link_list::LinkedList; use std::fmt::Error; +use std::mem; use std::mem::MaybeUninit; +use std::ptr::NonNull; // In a slots, the number of slot. const SLOTS_NUM: usize = 64; @@ -49,7 +51,7 @@ pub(crate) struct Wheel { // These corresponding timers have expired, // and are ready to be triggered. - trigger: VecDeque, + trigger: LinkedList, } impl Wheel { @@ -109,8 +111,8 @@ impl Wheel { } // Insert the corresponding TimerHandle into the specified position in the timing wheel. - pub(crate) fn insert(&mut self, timer_handle: TimerHandle) -> Result { - let expiration = unsafe { timer_handle.inner().as_ref().expiration() }; + pub(crate) fn insert(&mut self, mut clock_entry: NonNull) -> Result { + let expiration = unsafe { clock_entry.as_ref().expiration() }; if expiration <= self.elapsed() { // This means that the timeout period has passed, @@ -119,25 +121,24 @@ impl Wheel { } let level = self.find_level(expiration); - // Unsafe access to timer_handle is only unsafe when Sleep Drop, + // Unsafe access to clock_entry is only unsafe when Sleep Drop, // `Sleep` here does not go into `Ready`. - unsafe { timer_handle.inner().as_mut().set_level(level) }; + unsafe { clock_entry.as_mut().set_level(level) }; - self.levels[level].insert(timer_handle, self.elapsed); + self.levels[level].insert(clock_entry, self.elapsed); Ok(expiration) } - pub(crate) fn cancel(&mut self, timer_handle: &TimerHandle) { - // Unsafe access to timer_handle is only unsafe when Sleep Drop, + pub(crate) fn cancel(&mut self, clock_entry: NonNull) { + // Unsafe access to clock_entry is only unsafe when Sleep Drop, // `Sleep` here does not go into `Ready`. - let level = unsafe { timer_handle.inner().as_ref().level() }; - self.levels[level].cancel(timer_handle); - for (index, handle) in self.trigger.iter().enumerate() { - if handle == timer_handle { - self.trigger.remove(index).unwrap(); - break; - } + let level = unsafe { clock_entry.as_ref().level() }; + self.levels[level].cancel(clock_entry); + + // Caller has unique access to the linked list and the node is not in any other linked list. + unsafe { + LinkedList::remove(clock_entry); } } @@ -163,7 +164,7 @@ impl Wheel { } // Determine which timers have timed out at the current time. - pub(crate) fn poll(&mut self, now: u64) -> Option { + pub(crate) fn poll(&mut self, now: u64) -> Option> { loop { if let Some(handle) = self.trigger.pop_back() { return Some(handle); @@ -204,13 +205,13 @@ pub struct Level { occupied: u64, // slots in a level. - slots: [VecDeque; SLOTS_NUM], + slots: [LinkedList; SLOTS_NUM], } impl Level { // Specify the level and create a Level structure. pub(crate) fn new(level: usize) -> Self { - let mut slots: [MaybeUninit>; SLOTS_NUM] = + let mut slots: [MaybeUninit>; SLOTS_NUM] = unsafe { MaybeUninit::uninit().assume_init() }; for slot in slots.iter_mut() { @@ -218,7 +219,7 @@ impl Level { } unsafe { - let slots = std::mem::transmute::<_, [VecDeque; SLOTS_NUM]>(slots); + let slots = mem::transmute::<_, [LinkedList; SLOTS_NUM]>(slots); Self { level, occupied: 0, @@ -228,33 +229,31 @@ impl Level { } // Based on the elapsed which the current time wheel is running, - // and the expected expiration time of the timer_handle, + // and the expected expiration time of the clock_entry, // find the corresponding slot and insert it. - pub(crate) fn insert(&mut self, timer_handle: TimerHandle, elapsed: u64) { - let duration = unsafe { timer_handle.inner().as_ref().expiration() } - elapsed; - // Unsafe access to timer_handle is only unsafe when Sleep Drop, + pub(crate) fn insert(&mut self, mut clock_entry: NonNull, elapsed: u64) { + let duration = unsafe { clock_entry.as_ref().expiration() } - elapsed; + // Unsafe access to clock_entry is only unsafe when Sleep Drop, // `Sleep` here does not go into `Ready`. - unsafe { timer_handle.inner().as_mut().set_duration(duration) }; + unsafe { clock_entry.as_mut().set_duration(duration) }; let slot = ((duration >> (self.level * LEVELS_NUM)) % SLOTS_NUM as u64) as usize; - self.slots[slot].push_front(timer_handle); + self.slots[slot].push_front(clock_entry); self.occupied |= 1 << slot; } - pub(crate) fn cancel(&mut self, timer_handle: &TimerHandle) { - // Unsafe access to timer_handle is only unsafe when Sleep Drop, + pub(crate) fn cancel(&mut self, clock_entry: NonNull) { + // Unsafe access to clock_entry is only unsafe when Sleep Drop, // `Sleep` here does not go into `Ready`. - let duration = unsafe { timer_handle.inner().as_ref().duration() }; + let duration = unsafe { clock_entry.as_ref().duration() }; let slot = ((duration >> (self.level * LEVELS_NUM)) % SLOTS_NUM as u64) as usize; - for (index, handle) in self.slots[slot].iter().enumerate() { - if handle == timer_handle { - self.slots[slot].remove(index).unwrap(); - break; - } + // Caller has unique access to the linked list and the node is not in any other linked list. + unsafe { + LinkedList::remove(clock_entry); } if self.slots[slot].is_empty() { @@ -293,9 +292,9 @@ impl Level { } // Fetch all timers in a slot of the corresponding level. - pub(crate) fn take_slot(&mut self, slot: usize) -> VecDeque { + pub(crate) fn take_slot(&mut self, slot: usize) -> LinkedList { self.occupied &= !(1 << slot); - std::mem::take(&mut self.slots[slot]) + mem::take(&mut self.slots[slot]) } } -- Gitee