use std::{
fmt::{self, Display},
ptr, u64,
};
use super::Timer;
struct Entry<T: Timer> {
val: T,
when: u64,
id: u64,
}
pub struct OneTimerWheel<T: Timer> {
index: u64,
capation: u64,
num: u64,
step: u64,
fix_step: u64,
slots: Vec<Vec<Entry<T>>>,
parent: *mut OneTimerWheel<T>,
child: *mut OneTimerWheel<T>,
name: &'static str,
}
impl<T: Timer> OneTimerWheel<T> {
pub fn new(num: u64, step: u64, one_step: u64, name: &'static str) -> Self {
let mut slots = vec![];
for _ in 0..num {
slots.push(Vec::new());
}
Self {
index: 0,
capation: num * step,
num,
step,
fix_step: one_step * step,
slots,
parent: ptr::null_mut(),
child: ptr::null_mut(),
name,
}
}
pub fn clear(&mut self) {
for idx in 0..self.num as usize {
self.slots[idx].clear();
}
}
pub fn append(&mut self, next: *mut OneTimerWheel<T>) {
if self.child.is_null() {
unsafe {
(*next).parent = self;
self.child = next;
}
} else {
unsafe {
(*self.child).append(next);
}
}
}
fn add_timer(&mut self, entry: Entry<T>) {
let offset = entry.when;
self.add_timer_with_offset(entry, offset);
}
fn del_timer(&mut self, timer_id: u64) -> Option<T> {
for i in 0..self.num as usize {
let mut found_idx = None;
for (idx, val) in self.slots[i].iter().enumerate() {
if val.id == timer_id {
found_idx = Some(idx);
break;
}
}
if let Some(idx) = found_idx {
return Some(self.slots[i].remove(idx).val);
}
}
None
}
fn get_timer(&self, timer_id: &u64) -> Option<&T> {
for i in 0..self.num as usize {
for val in self.slots[i].iter() {
if &val.id == timer_id {
return Some(&val.val);
}
}
}
None
}
fn get_mut_timer(&mut self, timer_id: &u64) -> Option<&mut T> {
for i in 0..self.num as usize {
let mut found_idx = None;
let v = &mut self.slots[i];
for (idx, val) in v.iter().enumerate() {
if &val.id == timer_id {
found_idx = Some(idx);
break;
}
}
if let Some(idx) = found_idx {
return Some(&mut self.slots[i][idx].val);
}
}
None
}
fn add_step_timer(&mut self, entry: Entry<T>) {
let offset = entry.when % self.num;
self.add_timer_with_offset(entry, offset);
}
fn add_timer_with_offset(&mut self, entry: Entry<T>, offset: u64) {
if offset > self.capation {
let index = (self.index + self.num - 1) % self.num;
self.slots[index as usize].push(entry);
} else if offset <= self.fix_step && !self.child.is_null() {
unsafe {
(*self.child).add_timer_with_offset(entry, offset);
}
} else {
let index = (offset - 1) / self.fix_step;
let index = (index + self.index) % self.num;
self.slots[index as usize].push(entry);
}
}
pub fn update_index(
&mut self,
offset: u64,
remainder: u64,
result: &mut Vec<(u64, T)>,
) -> (u64, u64) {
let next = self.index + offset;
let mut all = 0;
for idx in self.index..next {
if all > self.num {
break;
}
all += 1;
let idx = idx % self.num;
let list = &mut self.slots[idx as usize];
for val in list.drain(..) {
result.push((val.id, val.val));
}
}
self.index = next % self.num;
if !self.child.is_null() {
unsafe {
let list = &mut self.slots[self.index as usize];
for mut val in list.drain(..) {
val.when = (val.when % self.step).saturating_sub(remainder);
if val.when == 0 {
result.push((val.id, val.val));
} else {
(*self.child).add_step_timer(val);
}
}
}
}
(next / self.num, next % self.num + remainder)
}
}
pub struct TimerWheel<T: Timer> {
greatest: *mut OneTimerWheel<T>,
lessest: *mut OneTimerWheel<T>,
one_step: u64,
next_timer_id: u64,
max_timer_id: u64,
delay_id: u64,
all_deltatime: u64,
len: usize,
}
impl<T: Timer> TimerWheel<T> {
pub fn new() -> Self {
Self {
greatest: ptr::null_mut(),
lessest: ptr::null_mut(),
next_timer_id: 1,
max_timer_id: u64::MAX,
delay_id: 0,
one_step: 1,
all_deltatime: 0,
len: 0,
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn clear(&mut self) {
let mut wheel = self.lessest;
while !wheel.is_null() {
unsafe {
(*wheel).clear();
wheel = (*wheel).parent;
}
}
self.len = 0;
}
pub fn get_one_step(&self) -> u64 {
self.one_step
}
pub fn set_one_step(&mut self, step: u64) {
self.one_step = step.max(1);
}
pub fn append_timer_wheel(&mut self, slots: u64, name: &'static str) {
debug_assert!(self.len == 0, "必须时轮为空才可改变时轮");
let step = if self.greatest.is_null() {
self.one_step
} else {
let mut now_step = 1;
let mut node = self.greatest;
unsafe {
while !node.is_null() {
now_step *= (*node).capation;
node = (*node).child;
}
}
now_step / self.one_step
};
let one = Box::into_raw(Box::new(OneTimerWheel::new(slots, step, self.one_step, name)));
self.delay_id = self.delay_id.max(slots * step);
if self.lessest.is_null() {
self.lessest = one;
self.greatest = one;
} else {
unsafe {
let child = self.greatest;
(*one).append(child);
self.greatest = one;
}
}
}
pub fn update_deltatime(&mut self, delta: u64) -> Option<Vec<(u64, T)>> {
debug_assert!(self.one_step > 0);
self.update_now(self.all_deltatime.wrapping_add(delta))
}
pub fn update_now(&mut self, now: u64) -> Option<Vec<(u64, T)>> {
debug_assert!(self.one_step > 0);
self.all_deltatime = now;
let mut offset = self.all_deltatime / self.one_step;
if offset < self.delay_id {
return None;
}
self.all_deltatime -= offset * self.one_step;
let mut remainder = 0;
let mut result = vec![];
let mut wheel = self.lessest;
while !wheel.is_null() {
unsafe {
(offset, remainder) = (*wheel).update_index(offset, remainder, &mut result);
if offset == 0 {
break;
}
wheel = (*wheel).parent;
}
}
self.calc_delay_id();
self.len -= result.len();
Some(result)
}
pub fn update_deltatime_with_callback<F>(&mut self, delta: u64, f: &mut F)
where
F: FnMut(&mut Self, u64, T) -> Option<(u64, T)>,
{
debug_assert!(self.one_step > 0);
self.update_now_with_callback(self.all_deltatime.wrapping_add(delta), f);
}
pub fn update_now_with_callback<F>(&mut self, now: u64, f: &mut F)
where
F: FnMut(&mut Self, u64, T) -> Option<(u64, T)>,
{
debug_assert!(self.one_step > 0);
if let Some(result) = self.update_now(now) {
let mut collect_result = vec![];
for r in result.into_iter() {
if let Some(v) = (*f)(self, r.0, r.1) {
collect_result.push(v);
}
}
for (timer_id, val) in collect_result.drain(..) {
self.add_timer_by_id(timer_id, val);
}
}
}
pub fn calc_delay_id(&mut self) {
let mut next_delay_id = 0;
let mut wheel = self.lessest;
'outer: while !wheel.is_null() {
unsafe {
let (step, index, cap) = ((*wheel).step, (*wheel).index, (*wheel).num);
for i in 0..cap {
let index = (index + i) % cap;
if !(*wheel).slots[index as usize].is_empty() {
next_delay_id = (i + 1) * step;
break 'outer;
}
}
next_delay_id = cap * step;
wheel = (*wheel).parent;
}
}
self.delay_id = next_delay_id / self.one_step;
}
pub fn del_timer(&mut self, timer_id: u64) -> Option<T> {
let mut wheel = self.lessest;
while !wheel.is_null() {
unsafe {
if let Some(v) = (*wheel).del_timer(timer_id) {
self.len -= 1;
return Some(v);
}
wheel = (*wheel).parent;
}
}
None
}
pub fn get_timer(&self, timer_id: &u64) -> Option<&T> {
let mut wheel = self.lessest;
while !wheel.is_null() {
unsafe {
if let Some(v) = (*wheel).get_timer(timer_id) {
return Some(v);
}
wheel = (*wheel).parent;
}
}
None
}
pub fn get_mut_timer(&mut self, timer_id: &u64) -> Option<&mut T> {
let mut wheel = self.lessest;
while !wheel.is_null() {
unsafe {
if let Some(v) = (*wheel).get_mut_timer(timer_id) {
return Some(v);
}
wheel = (*wheel).parent;
}
}
None
}
pub fn get_max_timerid(&self) -> u64 {
self.max_timer_id
}
pub fn set_max_timerid(&mut self, max: u64) {
self.max_timer_id = max;
}
fn get_next_timerid(&mut self) -> u64 {
let timer_id = self.next_timer_id;
if self.next_timer_id >= self.max_timer_id {
self.next_timer_id = 1;
} else {
self.next_timer_id = self.next_timer_id + 1;
}
timer_id
}
pub fn add_timer(&mut self, val: T) -> u64 {
debug_assert!(!self.greatest.is_null(), "必须设置时轮才能添加元素");
let timer_id: u64 = self.get_next_timerid();
self.add_timer_by_id(timer_id, val);
timer_id
}
pub fn add_timer_by_id(&mut self, timer_id: u64, mut val: T) {
let entry = Entry {
when: val.when_mut().max(1),
val,
id: timer_id,
};
self.delay_id = self.delay_id.min(entry.when / self.one_step);
unsafe {
(*self.greatest).add_timer(entry);
}
self.len += 1;
}
pub fn get_delay_id(&self) -> u64 {
self.delay_id
}
}
impl<T: Timer> Display for TimerWheel<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("TimerWheel {\r\n")?;
let mut wheel = self.greatest;
while !wheel.is_null() {
unsafe {
f.write_fmt(format_args!(
"{}, slots: {}, step: {}",
(*wheel).name,
(*wheel).slots.len(),
(*wheel).step
))?;
wheel = (*wheel).child;
}
}
f.write_str("}")
}
}
impl<T: Timer> Drop for TimerWheel<T> {
fn drop(&mut self) {
let mut wheel = self.greatest;
while !wheel.is_null() {
unsafe {
let val = *Box::from_raw(wheel);
wheel = val.child;
}
}
}
}