librust/r9/src/xtimer.rs
2023-11-08 00:45:06 +00:00

540 lines
17 KiB
Rust

use std::rc::{Rc, Weak};
use std::cell::RefCell;
use std::any::Any;
use std::cmp;
use std::time::{Instant};
use r9_macro::SharedFromSelf;
use r9_macro_derive::SharedFromSelf;
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 XTimerAttacherRp = Rc::<RefCell::<XTimerAttacher>>;
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 XTimerAttacher {
timers: TimerListListHeadRp,
}
#[derive(Clone)]
enum TimerType {
Timeout,
Interval
}
impl Default for TimerType {
fn default() -> Self
{
return TimerType::Timeout;
}
}
#[derive(Default)]
pub struct TimerList {
holder: Option<TimerListRp>,
wp: Option<Rc::<TimerListRp>>,
timer_entry: TimerListListHeadRp,
attach_entry: TimerListListHeadRp,
timer_type: TimerType,
expire_time: i32,
expires: i64,
cb: Option<TimerCb>,
}
#[derive(SharedFromSelf)]
pub struct XTimer {
free_timer_num: i32,
free_timer_list: TimerListListHeadRp,
running_timer: TimerListWp,
timer_tick: i64,
get_tick_count: Option<Box<dyn Fn () -> i64>>,
cache_timer_num: i32,
work_list: TimerListListHeadRp,
tv1: Vec<TimerListListHeadRp>,
tv2: Vec<TimerListListHeadRp>,
tv3: Vec<TimerListListHeadRp>,
tv4: Vec<TimerListListHeadRp>,
tv5: Vec<TimerListListHeadRp>,
_self_wp: Weak::<RefCell::<Self>>,
}
impl XTimer {
pub fn new() -> Rc::<RefCell::<Self>> {
let this = Rc::new(RefCell::new(XTimer{
free_timer_num: 0,
free_timer_list: Default::default(),
running_timer: Default::default(),
timer_tick: Default::default(),
get_tick_count: Default::default(),
cache_timer_num: 0,
work_list: Default::default(),
tv1: Vec::with_capacity(TVR_SIZE),
tv2: Vec::with_capacity(TVN_SIZE),
tv3: Vec::with_capacity(TVN_SIZE),
tv4: Vec::with_capacity(TVN_SIZE),
tv5: Vec::with_capacity(TVN_SIZE),
_self_wp: Default::default(),
}));
this.borrow_mut()._self_wp = Rc::downgrade(&this);
return this;
}
pub fn init(&mut self,
get_tick_count: Box<dyn Fn () -> i64>,
gctime: i32,
cache_timer_num: i32) {
self.get_tick_count = Some(get_tick_count);
self.cache_timer_num = cache_timer_num;
self.free_timer_num = 0;
self.free_timer_list = crate::ListHead::<TimerList>::new_head();
self.work_list = crate::ListHead::<TimerList>::new_head();
for _ in 0..TVR_SIZE {
self.tv1.push(crate::ListHead::<TimerList>::new_head());
}
for _ in 0..TVN_SIZE {
self.tv2.push(crate::ListHead::<TimerList>::new_head());
self.tv3.push(crate::ListHead::<TimerList>::new_head());
self.tv4.push(crate::ListHead::<TimerList>::new_head());
self.tv5.push(crate::ListHead::<TimerList>::new_head());
}
match &self.get_tick_count {
Some(v) => {
self.timer_tick = (*v)();
}
None => {
}
}
{
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);
}
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.clone().unwrap()) > 0 {
p.borrow_mut().wp = Some(Rc::new(p.borrow().holder.clone().unwrap()));
}
} 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 = Some(p.clone());
{
let z = Some(Rc::new(p.borrow().holder.clone().unwrap()));
p.borrow_mut().wp = z;
}
p.borrow_mut().timer_entry = crate::ListHead::<TimerList>::new_node(
Rc::downgrade(&p)
);
p.borrow_mut().attach_entry = crate::ListHead::<TimerList>::new_head();
}
return p;
}
fn cascade(&self, idx: usize) -> usize {
let index = self.get_timer_index(idx);
let tv : &[TimerListListHeadRp];
match idx {
0 => {
tv = &self.tv2;
}
1 => {
tv = &self.tv3;
}
2 => {
tv = &self.tv4;
}
3 => {
tv = &self.tv5;
}
_ => {
tv = &self.tv5;
}
}
if !tv[index].borrow().empty() {
let cascade_list = crate::ListHead::<TimerList>::new_head();
crate::ListHead::<TimerList>::replace_init
(&tv[index],
&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;
}
fn fetch_work_list(&mut self, tick: i64) -> bool {
if 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;
crate::ListHead::<TimerList>::replace_init
(&self.tv1[index],
&self.work_list);
return true;
} else {
return false;
}
}
pub fn update(this: &Rc::<RefCell::<XTimer>>) {
let tick = (*this.borrow().get_tick_count.as_ref().unwrap())();
let work_list = this.borrow().work_list.clone();
while this.borrow_mut().fetch_work_list(tick) {
while !work_list.borrow().empty() {
{
let timer = &work_list.borrow().first_entry();
this.borrow_mut().running_timer = timer.clone();
match &mut timer.upgrade().unwrap().borrow_mut().cb {
Some(v) => {
(*v)(TimerEvent::Exec, None);
}
None => {
}
}
}
{
let running_timer = this.borrow().running_timer.clone();
match running_timer.upgrade() {
Some(v) => {
let timer_wp = Rc::downgrade(&v.borrow().wp.as_ref().unwrap());
let timer_type = v.borrow().timer_type.clone();
let expire_time = v.borrow().expire_time;
match timer_type {
TimerType::Timeout => {
this.borrow_mut().internal_delete
(timer_wp,
false);
}
TimerType::Interval => {
this.borrow_mut().internal_modify(
timer_wp,
expire_time
);
}
}
}
None => {
}
}
}
}
}
this.borrow_mut().running_timer = Weak::new();
}
fn internal_add(&mut self,
timer_type: TimerType,
expire_time: i32,
cb: TimerCb,
attacher: Option<XTimerAttacherRp>) -> XTimerWp {
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;
match &self.get_tick_count {
Some(v) => {
t.borrow_mut().expires = (*v)() + expire_time as i64;
}
None => {
}
}
match attacher {
Some(v) => {
crate::ListHead::<TimerList>::add_tail
(&v.borrow().timers,
&t.borrow_mut().attach_entry);
}
None => {
}
}
self.internal_add2(&t);
return Rc::downgrade(&t.borrow().wp.clone().unwrap());
}
fn internal_add2(&self, t: &Rc::<RefCell::<TimerList>>) {
let idx = t.borrow().expires - self.timer_tick;
let index;
let vec: &Rc::<RefCell::<crate::ListHead<TimerList>>>;
if idx < 0 {
index = self.timer_tick & (TVR_MASK as i64);
vec = &self.tv1[index as usize];
} else if idx < TVR_SIZE as i64 {
index = t.borrow().expires & (TVR_MASK as i64);
vec = &self.tv1[index as usize];
} else if idx < (1 << (TVR_BITS + TVN_BITS)) {
index = (t.borrow().expires >> TVR_BITS) & (TVN_MASK as i64);
vec = &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 = &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 = &self.tv4[index as usize];
} else {
index = (t.borrow().expires >> (TVR_BITS + 3 * TVN_BITS)) & (TVN_MASK as i64);
vec = &self.tv5[index as usize];
}
crate::ListHead::<TimerList>::add_tail(&vec, &t.borrow_mut().timer_entry);
}
fn internal_delete(&mut self, timer_wp: XTimerWp, 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.clone().unwrap()) > 0 {
v.borrow_mut().wp = Some(Rc::new(v.borrow().holder.clone().unwrap()));
}
crate::ListHead::<TimerList>::add_tail
(&self.free_timer_list,
&v.borrow_mut().attach_entry);
self.free_timer_num += 1;
}
None => {
}
}
}
fn internal_modify(&self, timer_wp: XTimerWp, expire_time: i32) {
self.detach_timer(&timer_wp.upgrade().unwrap());
let timer = timer_wp.clone().upgrade().unwrap().clone();
timer.borrow_mut().expire_time = expire_time;
timer.borrow_mut().expires =
(*self.get_tick_count.as_ref().unwrap())() +
expire_time as i64;
self.internal_add2(&timer);
}
pub fn set_timeout(&mut self, time: i32, cb: TimerCb) -> XTimerWp {
return self.internal_add(TimerType::Timeout, time, cb, None);
}
pub fn set_timeout_ex
(&mut self, time: i32, cb: TimerCb, attacher: XTimerAttacherRp) -> XTimerWp {
return self.internal_add(TimerType::Timeout, time, cb, Some(attacher));
}
pub fn set_interval(&mut self, time: i32, cb: TimerCb) -> XTimerWp {
return self.internal_add(TimerType::Interval, time, cb, None);
}
pub fn set_interval_ex
(&mut self, time: i32, cb: TimerCb, attacher: XTimerAttacherRp) -> XTimerWp {
return self.internal_add(TimerType::Interval, time, cb, Some(attacher));
}
pub fn fire_event(&mut self,
timer_wp: XTimerWp,
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: XTimerWp, expire_time: i32) {
match timer_wp.upgrade() {
Some(_) => {
}
None => {
}
}
self.internal_modify(timer_wp, expire_time);
}
pub fn delete_current_timer(&mut self) {
match self.running_timer.upgrade() {
Some(v) => {
self.internal_delete(Rc::downgrade(&v.borrow().wp.clone().unwrap()), 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: XTimerWp) {
match timer_wp.upgrade() {
Some(_) => {
self.internal_delete(timer_wp, false);
}
None => {
}
}
}
pub fn get_remain_time(&mut self, timer_wp: XTimerWp) -> i64 {
match timer_wp.upgrade() {
Some(t) => {
match &self.get_tick_count {
Some(v) => {
let remain_time = t.borrow().expires - (*v)();
return cmp::max(remain_time, 0);
}
None => {
return 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>>>) {
let now = Instant::now();
//println!("now: {:?}", now);
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()
}
}
}