1
This commit is contained in:
parent
e870e4cb03
commit
978ddae947
465
src/timer.rs
465
src/timer.rs
@ -1,465 +0,0 @@
|
|||||||
use std::rc::{Rc, Weak};
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::any::Any;
|
|
||||||
use std::cmp;
|
|
||||||
use r9_macro::SharedFromSelf;
|
|
||||||
use r9_macro_derive::SharedFromSelf;
|
|
||||||
|
|
||||||
/*
|
|
||||||
use proc_macro::TokenStream;
|
|
||||||
use quote::quote;
|
|
||||||
use syn;
|
|
||||||
*/
|
|
||||||
|
|
||||||
const TVN_BITS: usize = 6;
|
|
||||||
const TVR_BITS: usize = 8;
|
|
||||||
const TVN_SIZE: usize = 1 << TVN_BITS;
|
|
||||||
const TVR_SIZE: usize = 1 << TVR_BITS;
|
|
||||||
const TVN_MASK: usize = TVN_SIZE - 1;
|
|
||||||
const TVR_MASK: usize = TVR_SIZE - 1;
|
|
||||||
|
|
||||||
pub type TimerAttacherRp = Rc::<RefCell::<TimerAttacher>>;
|
|
||||||
pub type XTimerWp = Weak::<Rc::<RefCell::<TimerList>>>;
|
|
||||||
pub type TimerCb = Box::<dyn FnMut (TimerEvent, Option<Vec<Rc::<dyn Any>>>)>;
|
|
||||||
type TimerListListHeadRp = Rc::<RefCell::<crate::ListHead<TimerList>>>;
|
|
||||||
type TimerListRp = Rc::<RefCell::<TimerList>>;
|
|
||||||
type TimerListWp = Weak::<RefCell::<TimerList>>;
|
|
||||||
|
|
||||||
pub enum TimerEvent {
|
|
||||||
Exec,
|
|
||||||
Delete,
|
|
||||||
Destory,
|
|
||||||
Custom(i32)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TimerAttacher {
|
|
||||||
timers: TimerListListHeadRp,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TimerType {
|
|
||||||
Timeout,
|
|
||||||
Interval
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TimerType {
|
|
||||||
|
|
||||||
fn default() -> Self
|
|
||||||
{
|
|
||||||
return TimerType::Timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct TimerList {
|
|
||||||
holder: TimerListRp,
|
|
||||||
wp: Rc::<TimerListRp>,
|
|
||||||
timer_entry: TimerListListHeadRp,
|
|
||||||
attach_entry: TimerListListHeadRp,
|
|
||||||
timer_type: TimerType,
|
|
||||||
expire_time: i32,
|
|
||||||
expires: i64,
|
|
||||||
|
|
||||||
cb: Option<TimerCb>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(SharedFromSelf)]
|
|
||||||
pub struct Timer {
|
|
||||||
free_timer_num: i32,
|
|
||||||
free_timer_list: TimerListListHeadRp,
|
|
||||||
running_timer: TimerListWp,
|
|
||||||
timer_tick: i64,
|
|
||||||
get_tick_count: fn () -> i64,
|
|
||||||
cache_timer_num: i32,
|
|
||||||
work_list: TimerListListHeadRp,
|
|
||||||
tv1: [TimerListListHeadRp; TVR_SIZE],
|
|
||||||
tv2: [TimerListListHeadRp; TVN_SIZE],
|
|
||||||
tv3: [TimerListListHeadRp; TVN_SIZE],
|
|
||||||
tv4: [TimerListListHeadRp; TVN_SIZE],
|
|
||||||
tv5: [TimerListListHeadRp; TVN_SIZE],
|
|
||||||
_self_wp: Weak::<RefCell::<Self>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Timer {
|
|
||||||
|
|
||||||
pub fn init(mut self,
|
|
||||||
get_tick_count: fn () -> i64,
|
|
||||||
gctime: i32,
|
|
||||||
cache_timer_num: i32) {
|
|
||||||
self.get_tick_count = get_tick_count;
|
|
||||||
self.cache_timer_num = cache_timer_num;
|
|
||||||
self.free_timer_num = 0;
|
|
||||||
self.mut_traverse_timer_list(
|
|
||||||
&mut |timer_list: &mut TimerListListHeadRp| {
|
|
||||||
*timer_list = crate::ListHead::<TimerList>::new_head();
|
|
||||||
});
|
|
||||||
self.timer_tick = (self.get_tick_count)();
|
|
||||||
{
|
|
||||||
let self_wp = self.shared_from_self();
|
|
||||||
let cb = Box::new(
|
|
||||||
move |event: TimerEvent, args: Option<Vec<Rc::<dyn Any>>>| {
|
|
||||||
self_wp.borrow_mut().gc_timer(event, args);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
self.set_interval(gctime, cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn traverse_timer_list(&self, cb: &mut dyn FnMut (&TimerListListHeadRp)) {
|
|
||||||
(*cb)(&self.work_list);
|
|
||||||
let mut for_each_cb = |tv: &[TimerListListHeadRp]| {
|
|
||||||
for i in 0..tv.len() {
|
|
||||||
(*cb)(&tv[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
for_each_cb(&self.tv1);
|
|
||||||
for_each_cb(&self.tv2);
|
|
||||||
for_each_cb(&self.tv3);
|
|
||||||
for_each_cb(&self.tv4);
|
|
||||||
for_each_cb(&self.tv5);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mut_traverse_timer_list(&mut self, cb: &mut dyn FnMut (&mut TimerListListHeadRp)) {
|
|
||||||
(*cb)(&mut self.work_list);
|
|
||||||
let mut for_each_cb = |tv: &mut [TimerListListHeadRp]| {
|
|
||||||
for i in 0..tv.len() {
|
|
||||||
(*cb)(&mut tv[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
for_each_cb(&mut self.tv1);
|
|
||||||
for_each_cb(&mut self.tv2);
|
|
||||||
for_each_cb(&mut self.tv3);
|
|
||||||
for_each_cb(&mut self.tv4);
|
|
||||||
for_each_cb(&mut self.tv5);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn uninit(&mut self) {
|
|
||||||
self.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear(&mut self) {
|
|
||||||
let free_timer = |head: &TimerListListHeadRp| {
|
|
||||||
while !head.borrow().empty() {
|
|
||||||
let timer = &head.borrow().first_entry().upgrade().unwrap();
|
|
||||||
self.detach_timer(timer);
|
|
||||||
if timer.borrow().attach_entry.borrow().empty() {
|
|
||||||
timer.borrow().attach_entry.borrow_mut().del_init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.traverse_timer_list(
|
|
||||||
&mut |timer_list: &TimerListListHeadRp| {
|
|
||||||
free_timer(timer_list);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_timer_list(&mut self) -> Rc::<RefCell::<TimerList>> {
|
|
||||||
let p: Rc::<RefCell::<TimerList>>;
|
|
||||||
if self.free_timer_list.borrow().empty() {
|
|
||||||
p = self.free_timer_list.borrow().first_entry().upgrade().unwrap();
|
|
||||||
if Rc::weak_count(&p.borrow().wp) > 0 {
|
|
||||||
p.borrow_mut().wp = Rc::new(p.borrow().holder.clone());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p = Rc::new(RefCell::new(TimerList{
|
|
||||||
holder: Default::default(),
|
|
||||||
wp: Default::default(),
|
|
||||||
timer_entry: Default::default(),
|
|
||||||
attach_entry: Default::default(),
|
|
||||||
timer_type: TimerType::Timeout,
|
|
||||||
expire_time: 0,
|
|
||||||
expires: 0,
|
|
||||||
cb: None,
|
|
||||||
}));
|
|
||||||
p.borrow_mut().holder = p.clone();
|
|
||||||
p.borrow_mut().wp = Rc::new(p.borrow().holder.clone());
|
|
||||||
p.borrow_mut().timer_entry = crate::ListHead::<TimerList>::new_node(
|
|
||||||
Rc::downgrade(&p.borrow().holder)
|
|
||||||
);
|
|
||||||
p.borrow_mut().attach_entry = crate::ListHead::<TimerList>::new_head();
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cascade(&mut self, idx: usize) -> usize {
|
|
||||||
let index = self.get_timer_index(idx);
|
|
||||||
let tv : &mut [TimerListListHeadRp];
|
|
||||||
match idx {
|
|
||||||
0 => {
|
|
||||||
tv = &mut self.tv2;
|
|
||||||
}
|
|
||||||
1 => {
|
|
||||||
tv = &mut self.tv3;
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
tv = &mut self.tv4;
|
|
||||||
}
|
|
||||||
3 => {
|
|
||||||
tv = &mut self.tv5;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
tv = &mut self.tv5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !tv[index].borrow().empty() {
|
|
||||||
let mut cascade_list = crate::ListHead::<TimerList>::new_head();
|
|
||||||
tv[index].borrow_mut().replace_init(&mut cascade_list);
|
|
||||||
while !cascade_list.borrow().empty() {
|
|
||||||
let timer = &cascade_list.borrow().first_entry().upgrade().unwrap();
|
|
||||||
timer.borrow_mut().timer_entry.borrow_mut().del_init();
|
|
||||||
self.internal_add2(timer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_timer_index(&self, index : usize) -> usize {
|
|
||||||
return ((self.timer_tick as usize) >> (TVR_BITS + index * TVN_BITS)) & TVN_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self) {
|
|
||||||
let tick = (self.get_tick_count)();
|
|
||||||
while tick >= self.timer_tick {
|
|
||||||
let index = (self.timer_tick & (TVR_MASK as i64)) as usize;
|
|
||||||
if index == 0 &&
|
|
||||||
self.cascade(0) == 0 &&
|
|
||||||
self.cascade(1) == 0 &&
|
|
||||||
self.cascade(2) == 0 {
|
|
||||||
self.cascade(3);
|
|
||||||
}
|
|
||||||
self.timer_tick += 1;
|
|
||||||
|
|
||||||
self.work_list.borrow_mut().replace_init(&mut self.tv1[index]);
|
|
||||||
while !self.work_list.borrow().empty() {
|
|
||||||
let timer = &self.work_list.borrow().first_entry();
|
|
||||||
self.running_timer = timer.clone();
|
|
||||||
match &mut timer.upgrade().unwrap().borrow_mut().cb {
|
|
||||||
Some(v) => {
|
|
||||||
(*v)(TimerEvent::Exec, None);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match self.running_timer.upgrade() {
|
|
||||||
Some(v) => {
|
|
||||||
match v.borrow().timer_type {
|
|
||||||
TimerType::Timeout => {
|
|
||||||
self.internal_delete(Rc::downgrade(&v.borrow().wp), false);
|
|
||||||
}
|
|
||||||
TimerType::Interval => {
|
|
||||||
self.modify(Rc::downgrade(&v.borrow().wp),
|
|
||||||
v.borrow().expire_time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.running_timer = Weak::new();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn internal_add(&mut self,
|
|
||||||
timer_type: TimerType,
|
|
||||||
expire_time: i32,
|
|
||||||
cb: TimerCb,
|
|
||||||
attacher: Option<TimerAttacherRp>) -> TimerWp {
|
|
||||||
let t = self.new_timer_list();
|
|
||||||
t.borrow_mut().cb = Some(cb);
|
|
||||||
t.borrow_mut().timer_type = timer_type;
|
|
||||||
t.borrow_mut().expire_time = expire_time;
|
|
||||||
t.borrow_mut().expires = (self.get_tick_count)() + expire_time as i64;
|
|
||||||
match attacher {
|
|
||||||
Some(v) => {
|
|
||||||
v.borrow_mut().timers.borrow_mut().add_tail(&t.borrow_mut().attach_entry);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.internal_add2(&t);
|
|
||||||
return Rc::downgrade(&t.borrow().wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn internal_add2(&mut self, t: &Rc::<RefCell::<TimerList>>) {
|
|
||||||
let idx = t.borrow().expires - self.timer_tick;
|
|
||||||
let index;
|
|
||||||
let vec: &mut Rc::<RefCell::<crate::ListHead<TimerList>>>;
|
|
||||||
if idx < 0 {
|
|
||||||
index = self.timer_tick & (TVR_MASK as i64);
|
|
||||||
vec = &mut self.tv1[index as usize];
|
|
||||||
} else if idx < TVR_SIZE as i64 {
|
|
||||||
index = t.borrow().expires & (TVR_MASK as i64);
|
|
||||||
vec = &mut self.tv1[index as usize];
|
|
||||||
} else if idx < (1 << (TVR_BITS + TVN_BITS)) {
|
|
||||||
index = (t.borrow().expires >> TVR_BITS) & (TVN_MASK as i64);
|
|
||||||
vec = &mut self.tv2[index as usize];
|
|
||||||
} else if idx < (1 << (TVR_BITS + 2 * TVN_BITS)) {
|
|
||||||
index = (t.borrow().expires >> (TVR_BITS + 1 * TVN_BITS)) & (TVN_MASK as i64);
|
|
||||||
vec = &mut self.tv3[index as usize];
|
|
||||||
} else if idx < (1 << (TVR_BITS + 3 * TVN_BITS)) {
|
|
||||||
index = (t.borrow().expires >> (TVR_BITS + 2 * TVN_BITS)) & (TVN_MASK as i64);
|
|
||||||
vec = &mut self.tv4[index as usize];
|
|
||||||
} else {
|
|
||||||
index = (t.borrow().expires >> (TVR_BITS + 3 * TVN_BITS)) & (TVN_MASK as i64);
|
|
||||||
vec = &mut self.tv5[index as usize];
|
|
||||||
}
|
|
||||||
vec.borrow_mut().add_tail(&t.borrow_mut().timer_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn internal_delete(&mut self, timer_wp: TimerWp, is_destory: bool) {
|
|
||||||
match timer_wp.upgrade() {
|
|
||||||
Some(v) => {
|
|
||||||
if Weak::ptr_eq(&self.running_timer, &Rc::downgrade(&v)) {
|
|
||||||
self.running_timer = Weak::new();
|
|
||||||
}
|
|
||||||
self.detach_timer(&*v);
|
|
||||||
match &mut v.borrow_mut().cb {
|
|
||||||
Some(cb) => {
|
|
||||||
if is_destory {
|
|
||||||
(*cb)(TimerEvent::Destory, None);
|
|
||||||
} else {
|
|
||||||
(*cb)(TimerEvent::Delete, None);
|
|
||||||
}
|
|
||||||
v.borrow_mut().cb = None;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if Rc::weak_count(&v.borrow().wp) > 0 {
|
|
||||||
v.borrow_mut().wp = Rc::new(v.borrow().holder.clone());
|
|
||||||
}
|
|
||||||
self.free_timer_list.borrow_mut().add_tail(&v.borrow_mut().timer_entry);
|
|
||||||
self.free_timer_num += 1;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_timeout(&mut self, time: i32, cb: TimerCb) -> TimerWp {
|
|
||||||
return self.internal_add(TimerType::Timeout, time, cb, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_timeout_ex
|
|
||||||
(&mut self, time: i32, cb: TimerCb, attacher: TimerAttacherRp) -> TimerWp {
|
|
||||||
return self.internal_add(TimerType::Timeout, time, cb, Some(attacher));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_interval(&mut self, time: i32, cb: TimerCb) -> TimerWp {
|
|
||||||
return self.internal_add(TimerType::Interval, time, cb, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_interval_ex
|
|
||||||
(&mut self, time: i32, cb: TimerCb, attacher: TimerAttacherRp) -> TimerWp {
|
|
||||||
return self.internal_add(TimerType::Interval, time, cb, Some(attacher));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fire_event(&mut self,
|
|
||||||
timer_wp: TimerWp,
|
|
||||||
e: TimerEvent,
|
|
||||||
args: Option<Vec<Rc::<dyn Any>>>) {
|
|
||||||
match timer_wp.upgrade() {
|
|
||||||
Some(t) => {
|
|
||||||
match &mut t.borrow_mut().cb {
|
|
||||||
Some(cb) => {
|
|
||||||
(*cb)(e, args);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modify(&mut self, timer_wp: TimerWp, expire_time: i32) {
|
|
||||||
match timer_wp.upgrade() {
|
|
||||||
Some(_) => {
|
|
||||||
self.modify(timer_wp, expire_time);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_current_timer(&mut self) {
|
|
||||||
match self.running_timer.upgrade() {
|
|
||||||
Some(v) => {
|
|
||||||
self.internal_delete(Rc::downgrade(&v.borrow().wp), false);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_running(&self) -> bool {
|
|
||||||
match self.running_timer.upgrade() {
|
|
||||||
Some(_) => {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(&mut self, timer_wp: TimerWp) {
|
|
||||||
match timer_wp.upgrade() {
|
|
||||||
Some(_) => {
|
|
||||||
self.internal_delete(timer_wp, false);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_remain_time(&mut self, timer_wp: TimerWp) -> i64 {
|
|
||||||
match timer_wp.upgrade() {
|
|
||||||
Some(t) => {
|
|
||||||
let remain_time = t.borrow().expires - (self.get_tick_count)();
|
|
||||||
return cmp::max(remain_time, 0);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_idle_time(&self) -> i64 {
|
|
||||||
let mut idle_time = 0;
|
|
||||||
let start_idx = (self.timer_tick as usize) & TVR_MASK;
|
|
||||||
for i in start_idx..self.tv1.len() {
|
|
||||||
if !self.tv1[i].borrow().empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
idle_time += 1;
|
|
||||||
}
|
|
||||||
return idle_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gc_timer(&mut self, e: TimerEvent, _args: Option<Vec<Rc::<dyn Any>>>) {
|
|
||||||
match e {
|
|
||||||
TimerEvent::Exec => {
|
|
||||||
while self.free_timer_num > self.cache_timer_num &&
|
|
||||||
!self.free_timer_list.borrow().empty() {
|
|
||||||
let timer = &self.free_timer_list.borrow().first_entry().upgrade().unwrap();
|
|
||||||
timer.borrow_mut().timer_entry.borrow_mut().del_init();
|
|
||||||
self.free_timer_num -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn detach_timer(&self, timer: &Rc::<RefCell::<TimerList>>) {
|
|
||||||
if !timer.borrow().timer_entry.borrow().empty() {
|
|
||||||
timer.borrow().timer_entry.borrow_mut().del_init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user