This commit is contained in:
aozhiwei 2022-12-14 10:21:44 +08:00
parent 2964212b5f
commit ffcbe9e7bf
2 changed files with 435 additions and 425 deletions

View File

@ -2,8 +2,6 @@
#include <a8/xtimer.h> #include <a8/xtimer.h>
typedef struct list_head XTimerDestoryHandle;
#define CONFIG_BASE_SMALL 0 #define CONFIG_BASE_SMALL 0
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
@ -46,12 +44,6 @@ struct xtimer_list {
a8::TimerCb cb; a8::TimerCb cb;
}; };
struct XTimerDestoryHandleNode
{
struct list_head entry;
std::function<void(xtimer_list*)> cb;
};
static void InternalAddXTimer(struct xtvec_base *base, struct xtimer_list *timer) static void InternalAddXTimer(struct xtvec_base *base, struct xtimer_list *timer)
{ {
long long expires = timer->expires; long long expires = timer->expires;
@ -85,66 +77,34 @@ static int Cascade(struct xtvec_base *base, struct xtvec *tv, int index)
struct xtimer_list *timer, *tmp; struct xtimer_list *timer, *tmp;
struct list_head tv_list; struct list_head tv_list;
// 将tv数组中以index为下标的定时器队列取出准备搬移
list_replace_init(tv->vec + index, &tv_list); list_replace_init(tv->vec + index, &tv_list);
// 根据超时时间,将队列中的定时器重新排队。定时器往上一级时间轮排队的过程就 // 在这里发生。
list_for_each_entry_safe(timer, tmp, &tv_list, entry) { list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
InternalAddXTimer(base, timer); InternalAddXTimer(base, timer);
} }
return index; return index;
} }
static inline int DetachTimer(struct xtimer_list *timer)
{
if (!list_empty(&timer->entry)) {
list_del_init(&timer->entry);
}
return 1;
}
static inline void InitTimerList(xtvec_base* base, xtimer_list* timer, int timer_type,
long long expires, int expire_time,
a8::TimerCb cb)
{
INIT_LIST_HEAD(&timer->destory_handle_list);
INIT_LIST_HEAD(&timer->entry);
INIT_LIST_HEAD(&timer->attach_entry);
timer->timer_type = timer_type;
timer->expires = expires;
timer->expire_time = expire_time;
timer->fixed_timer_execute_times = 0;
timer->base = base;
timer->cb = std::move(cb);
}
static xtimer_list* NewTimerList(xtvec_base* base_)
{
if (!list_empty(&base_->free_timer)) {
xtimer_list* timer = list_first_entry(&base_->free_timer, struct xtimer_list,entry);
list_del_init(&timer->entry);
base_->free_timer_num--;
return timer;
} else {
return new xtimer_list();
}
}
static void AddToFreeList(xtvec_base* base_, xtimer_list* timer)
{
list_add_tail(&timer->entry, &base_->free_timer);
base_->free_timer_num++;
}
namespace a8 namespace a8
{ {
typedef struct list_head XTimerDestoryHandle;
struct XTimerPtr struct XTimerPtr
{ {
xtimer_list* timer = nullptr; xtimer_list* timer = nullptr;
}; };
XTimer::XTimer() struct XTimerDestoryHandleNode
{
struct list_head entry;
std::function<void(xtimer_list*)> cb;
};
class XTimerImpl
{
public:
XTimerImpl()
{ {
base_ = new xtvec_base(); base_ = new xtvec_base();
base_->running_timer = nullptr; base_->running_timer = nullptr;
@ -161,16 +121,15 @@ namespace a8
} }
} }
XTimer::~XTimer() ~XTimerImpl()
{ {
#if 0 #if 0
Clear(); Clear();
#endif #endif
delete base_; A8_SAFE_DELETE(base_);
base_ = nullptr;
} }
void XTimer::Init(XGetTickCountFunc func, void* context, int gc_time, int cache_timer_num) void Init(XGetTickCountFunc func, void* context, int gc_time, int cache_timer_num)
{ {
get_tick_count_func_ = func; get_tick_count_func_ = func;
context_ = context; context_ = context;
@ -196,19 +155,14 @@ namespace a8
}); });
} }
void XTimer::Update() void Update()
{ {
if (get_tick_count_func_(context_) >= base_->timer_tick) { if (get_tick_count_func_(context_) >= base_->timer_tick) {
UpdateTimer(); UpdateTimer();
} }
} }
#if 0 void InternalSetTimeout(int time, TimerCb cb, Attacher* attacher, XTimerWp* wp)
void XTimer::AddDeadLineTimer(
int expire_time,
a8::TimerCbProc timer_cb,
a8::XTimerAttacher* attacher
)
{ {
xtimer_list *timer = ::NewTimerList(base_); xtimer_list *timer = ::NewTimerList(base_);
InitTimerList(base_, InitTimerList(base_,
@ -218,28 +172,34 @@ namespace a8
expire_time, expire_time,
timer_cb timer_cb
); );
ModifyTimerTimer(timer, expire_time);
#if 0 #if 0
ModifyTimer(timer, expire_time); std::shared_ptr<XTimerPtr> timer_ptr = std::make_shared<XTimerPtr>();
timer_ptr->timer = timer;
std::weak_ptr<XTimerPtr> result = timer_ptr;
AddTimerDestoryHandle
(result,
[timer_ptr] (xtimer_list* timer)
{
timer_ptr->timer = nullptr;
});
return result;
#endif #endif
} }
std::weak_ptr<XTimerPtr> XTimer::AddDeadLineTimerEx( void InternalSetInterval(int time, TimerCb cb, Attacher* attacher, XTimerWp* wp)
int expire_time,
a8::TimerCbProc timer_cb,
a8::XTimerAttacher* attacher
)
{ {
xtimer_list *timer = ::NewTimerList(base_); xtimer_list *timer = ::NewTimerList(base_);
InitTimerList(base_, InitTimerList(base_,
timer, timer,
0, 1,
get_tick_count_func_(context_) + expire_time, get_tick_count_func_(context_) + expire_time,
expire_time, expire_time,
timer_cb timer_cb);
); #if 0
#if 0
ModifyTimer(timer, expire_time); ModifyTimer(timer, expire_time);
#endif #endif
std::shared_ptr<XTimerPtr> timer_ptr = std::make_shared<XTimerPtr>(); std::shared_ptr<XTimerPtr> timer_ptr = std::make_shared<XTimerPtr>();
timer_ptr->timer = timer; timer_ptr->timer = timer;
@ -253,43 +213,17 @@ namespace a8
return result; return result;
} }
void XTimer::AddRepeatTimer( void FireEvent(XTimerWp& timer_wp, a8::Args* args)
int expire_time,
a8::TimerCbProc timer_cb,
a8::XTimerAttacher* attacher)
{
xtimer_list *timer = ::NewTimerList(base_);
InitTimerList(base_,
timer,
1,
get_tick_count_func_(context_) + expire_time,
expire_time,
timer_cb);
#if 0
ModifyTimer(timer, expire_time);
#endif
}
std::weak_ptr<XTimerPtr> XTimer::AddRepeatTimerEx(
int expire_time,
a8::TimerCbProc timer_cb,
a8::XTimerAttacher* attacher)
{ {
} }
void XTimer::FireUserEvent(std::weak_ptr<XTimerPtr>& timer_ptr, a8::Args& args) void ModifyTime(XTimerWp& timer_wp, int expire_time)
{ {
}
void XTimer::ModifyTimer(std::weak_ptr<XTimerPtr>& timer_ptr, int expire_time)
{
xtimer_list* timer = timer_ptr.lock()->timer;
DetachTimer(timer); DetachTimer(timer);
timer->expire_time = expire_time; timer->expire_time = expire_time;
if (timer->timer_type == 2) { if (timer->timer_type == 2) {
long long tick = get_tick_count_func_(context_); long long tick = get_tick_count_func(context_);
long long today_passed_seconds = time(nullptr) - a8::GetDaySeconds(time(nullptr), 0); long long today_passed_seconds = time(nullptr) - a8::GetDaySeconds(time(nullptr), 0);
timer->expires = (tick - today_passed_seconds * 1000) + expire_time; timer->expires = (tick - today_passed_seconds * 1000) + expire_time;
if (timer->fixed_timer_execute_times > 0) { if (timer->fixed_timer_execute_times > 0) {
@ -303,7 +237,7 @@ namespace a8
InternalAddXTimer(base_, timer); InternalAddXTimer(base_, timer);
} }
void XTimer::DeleteTimer(std::weak_ptr<XTimerPtr>& timer_ptr) void Delete(XTimerWp& timer_wp)
{ {
xtimer_list* timer = timer_ptr.lock()->timer; xtimer_list* timer = timer_ptr.lock()->timer;
if (!timer) { if (!timer) {
@ -330,7 +264,7 @@ namespace a8
AddToFreeList(base_, timer); AddToFreeList(base_, timer);
} }
long long XTimer::GetRemainTime(std::weak_ptr<XTimerPtr>& timer_ptr) long long GetRemainTime(XTimerWp& timer_wp)
{ {
xtimer_list* timer = timer_ptr.lock()->timer; xtimer_list* timer = timer_ptr.lock()->timer;
if (!timer) { if (!timer) {
@ -340,8 +274,19 @@ namespace a8
return std::max(remain_time, (long long)0); return std::max(remain_time, (long long)0);
} }
void XTimer::DestoryTimer(std::weak_ptr<XTimerPtr>& timer_ptr) bool IsRunning()
{ {
return base_->running_timer != nullptr;
}
void ClearAttacher(Attacher* attacher)
{
}
void DestoryAttacher(Attacher* attacher)
{
#if 0
xtimer_list* timer = timer_ptr.lock()->timer; xtimer_list* timer = timer_ptr.lock()->timer;
if (!timer) { if (!timer) {
abort(); abort();
@ -365,44 +310,98 @@ namespace a8
delete node; delete node;
} }
AddToFreeList(base_, timer); AddToFreeList(base_, timer);
#endif
} }
xtimer_list* XTimer::GetTimerByAttach(list_head* attach_entry) void XTimer::UpdateTimer()
{ {
struct xtvec_base *base = base_;
while (get_tick_count_func_(context_) >= base->timer_tick) {
struct list_head work_list;
struct list_head *head = &work_list;
int index = base->timer_tick & TVR_MASK;
if (!index &&
(!Cascade(base, &base->tv2, INDEX(0))) &&
(!Cascade(base, &base->tv3, INDEX(1))) &&
!Cascade(base, &base->tv4, INDEX(2))) {
Cascade(base, &base->tv5, INDEX(3));
} }
++base->timer_tick;
xtimer_list* XTimer::GetRunningTimer() list_replace_init(base->tv1.vec + index, &work_list);
while (!list_empty(head)) {
struct xtimer_list *timer;
timer = list_first_entry(head, struct xtimer_list,entry);
base->running_timer = timer;
if (timer->cb) {
timer->cb(TIMER_EXEC_EVENT, nullptr);
}
if (base_->running_timer) {
switch (timer->timer_type) {
case 1:
case 2: //循环类定时 fixed timer也是循环定时器
{ {
return base_->running_timer; if (timer->timer_type == 2) {
timer->fixed_timer_execute_times++;
} }
#if 0
XTimerDestoryHandle* XTimer::AddTimerDestoryHandle(std::weak_ptr<XTimerPtr>& timer_ptr, ModifyTimer(timer, timer->expire_time);
std::function<void(xtimer_list*)> cb) #endif
}
break;
default: //deadline timer
{ {
XTimerDestoryHandleNode* node = new XTimerDestoryHandleNode; DetachTimer(timer);
node->cb = cb; if (!list_empty(&timer->attach_entry)) {
list_add_tail(&node->entry, &timer_ptr.lock()->timer->destory_handle_list); list_del_init(&timer->attach_entry);
return &node->entry;
} }
while (!list_empty(&timer->destory_handle_list)) {
void XTimer::RemoveTimerDestoryHandle(XTimerDestoryHandle* handle) XTimerDestoryHandleNode* node = list_first_entry(&timer->destory_handle_list,
{ XTimerDestoryHandleNode,
if (!handle || list_empty(handle)) { entry);
abort();
}
XTimerDestoryHandleNode* node = list_entry(handle, XTimerDestoryHandleNode, entry);
list_del_init(&node->entry); list_del_init(&node->entry);
node->cb(timer);
delete node; delete node;
} }
AddToFreeList(base_, timer);
if (timer->cb) {
timer->cb(TIMER_DELETE_EVENT, nullptr);
}
}
break;
}
}
}
}
base->running_timer = nullptr;
}
bool XTimer::IsRunningTimer() void DeleteCurrentTimer()
{ {
} }
void XTimer::Clear() private:
void AddToFreeList(xtimer_list* timer)
{
list_add_tail(&timer->entry, &base_->free_timer);
base_->free_timer_num++;
}
xtimer_list* NewTimerList(xtvec_base* base_)
{
if (!list_empty(&base_->free_timer)) {
xtimer_list* timer = list_first_entry(&base_->free_timer, struct xtimer_list,entry);
list_del_init(&timer->entry);
base_->free_timer_num--;
return timer;
} else {
return new xtimer_list();
}
}
void ClearTimer()
{ {
auto free_timers = auto free_timers =
[] (list_head* head) [] (list_head* head)
@ -437,148 +436,163 @@ namespace a8
free_timers(&base_->free_timer); free_timers(&base_->free_timer);
} }
#endif XTimerDestoryHandle* AddTimerDestoryHandle(std::weak_ptr<XTimerPtr>& timer_ptr,
std::function<void(xtimer_list*)> cb)
{
XTimerDestoryHandleNode* node = new XTimerDestoryHandleNode;
node->cb = cb;
list_add_tail(&node->entry, &timer_ptr.lock()->timer->destory_handle_list);
return &node->entry;
}
void RemoveTimerDestoryHandle(XTimerDestoryHandle* handle)
{
if (!handle || list_empty(handle)) {
abort();
}
XTimerDestoryHandleNode* node = list_entry(handle, XTimerDestoryHandleNode, entry);
list_del_init(&node->entry);
delete node;
}
void InitTimerList(xtvec_base* base, xtimer_list* timer, int timer_type,
long long expires, int expire_time,
a8::TimerCb cb)
{
INIT_LIST_HEAD(&timer->destory_handle_list);
INIT_LIST_HEAD(&timer->entry);
INIT_LIST_HEAD(&timer->attach_entry);
timer->timer_type = timer_type;
timer->expires = expires;
timer->expire_time = expire_time;
timer->fixed_timer_execute_times = 0;
timer->base = base;
timer->cb = std::move(cb);
}
int DetachTimer(struct xtimer_list *timer)
{
if (!list_empty(&timer->entry)) {
list_del_init(&timer->entry);
}
return 1;
}
private:
xtvec_base* base_ = nullptr;
XGetTickCountFunc get_tick_count_func_ = nullptr;
void* context_ = nullptr;
int gc_time_ = 10;
int cache_timer_num_ = 100;
};
XTimer::XTimer()
{
impl_ = new XTimerImpl();
}
XTimer::~XTimer()
{
A8_SAFE_DELETE(impl_);
}
void XTimer::Init(XGetTickCountFunc func, void* context, int gc_time, int cache_timer_num)
{
impl_->Init(func, context, gc_time, cache_timer_num);
}
void XTimer::Update()
{
impl_->Update();
}
void XTimer::SetTimeout(int time, TimerCb cb) void XTimer::SetTimeout(int time, TimerCb cb)
{ {
impl_->InternalSetTimeout(time, cb, nullptr, nullptr);
} }
void XTimer::SetTimeoutEx(int time, TimerCb cb, Attacher* attacher) void XTimer::SetTimeoutEx(int time, TimerCb cb, Attacher* attacher)
{ {
impl_->InternalSetTimeout(time, cb, attacher, nullptr);
} }
XTimerWp XTimer::SetTimeoutWp(int time, TimerCb cb) XTimerWp XTimer::SetTimeoutWp(int time, TimerCb cb)
{ {
XTimerWp result;
impl_->InternalSetTimeout(time, cb, nullptr, &result);
return result;
} }
XTimerWp XTimer::SetTimeoutWpEx(int time, TimerCb cb, Attacher* attacher) XTimerWp XTimer::SetTimeoutWpEx(int time, TimerCb cb, Attacher* attacher)
{ {
XTimerWp result;
impl_->InternalSetTimeout(time, cb, attacherk, &result);
return result;
} }
void XTimer::SetInterval(int time, a8::TimerCb cb) void XTimer::SetInterval(int time, a8::TimerCb cb)
{ {
impl_->InternalSetInterval(time, cb, nullptr, nullptr);
} }
void XTimer::SetIntervalEx(int time, a8::TimerCb cb, Attacher* attacher) void XTimer::SetIntervalEx(int time, a8::TimerCb cb, Attacher* attacher)
{ {
impl_->InternalSetInterval(time, cb, attacker, nullptr);
} }
XTimerWp XTimer::SetIntervalWp(int time, TimerCb cb) XTimerWp XTimer::SetIntervalWp(int time, TimerCb cb)
{ {
XTimerWp result;
impl_->InternalSetInterval(time, cb, nullptr, &result);
return result;
} }
XTimerWp XTimer::SetIntervalWpEx(int time, TimerCb cb, Attacher* attacher) XTimerWp XTimer::SetIntervalWpEx(int time, TimerCb cb, Attacher* attacher)
{ {
XTimerWp result;
impl_->InternalSetInterval(time, cb, attacherk, &result);
return result;
} }
void XTimer::FireEvent(XTimerWp& timer_wp, a8::Args& args) void XTimer::FireEvent(XTimerWp& timer_wp, a8::Args* args)
{ {
impl_->FireEvent(timer_wp, args);
} }
void XTimer::ModifyTime(XTimerWp& timer_wp, int expire_time) void XTimer::ModifyTime(XTimerWp& timer_wp, int expire_time)
{ {
impl_->ModifyTime(timr_wp, expire_time);
} }
void XTimer::Delete(XTimerWp& timer_wp) void XTimer::Delete(XTimerWp& timer_wp)
{ {
impl_->Delete(timer_wp);
} }
long long XTimer::GetRemainTime(XTimerWp& timer_wp) long long XTimer::GetRemainTime(XTimerWp& timer_wp)
{ {
return impl_->GetRemainTime(timer_wp);
} }
bool XTimer::IsRunning() bool XTimer::IsRunning()
{ {
return impl_->IsRunning();
} }
void XTimer::ClearAttacher(Attacher* attacher) void XTimer::ClearAttacher(Attacher* attacher)
{ {
impl_->ClearAttacher(attacher);
} }
void XTimer::DestoryAttacher(Attacher* attacher) void XTimer::DestoryAttacher(Attacher* attacher)
{ {
impl_->DestoryAttacher(attacher);
}
void XTimer::UpdateTimer()
{
struct xtvec_base *base = base_;
while (get_tick_count_func_(context_) >= base->timer_tick) {
struct list_head work_list;
struct list_head *head = &work_list;
int index = base->timer_tick & TVR_MASK;
if (!index &&
(!Cascade(base, &base->tv2, INDEX(0))) &&
(!Cascade(base, &base->tv3, INDEX(1))) &&
!Cascade(base, &base->tv4, INDEX(2))) {
Cascade(base, &base->tv5, INDEX(3));
}
++base->timer_tick;
list_replace_init(base->tv1.vec + index, &work_list);
while (!list_empty(head)) {
struct xtimer_list *timer;
timer = list_first_entry(head, struct xtimer_list,entry);
base->running_timer = timer;
if (timer->cb) {
timer->cb(TIMER_EXEC_EVENT, nullptr);
}
if (base_->running_timer) {
switch (timer->timer_type) {
case 1:
case 2: //循环类定时 fixed timer也是循环定时器
{
if (timer->timer_type == 2) {
timer->fixed_timer_execute_times++;
}
#if 0
ModifyTimer(timer, timer->expire_time);
#endif
}
break;
default: //deadline timer
{
DetachTimer(timer);
if (!list_empty(&timer->attach_entry)) {
list_del_init(&timer->attach_entry);
}
while (!list_empty(&timer->destory_handle_list)) {
XTimerDestoryHandleNode* node = list_first_entry(&timer->destory_handle_list,
XTimerDestoryHandleNode,
entry);
list_del_init(&node->entry);
node->cb(timer);
delete node;
}
AddToFreeList(base_, timer);
if (timer->cb) {
timer->cb(TIMER_DELETE_EVENT, nullptr);
}
}
break;
}
}
}
}
base->running_timer = nullptr;
} }
void XTimer::DeleteCurrentTimer() void XTimer::DeleteCurrentTimer()
{ {
impl_->DeleteCurrentTimer();
} }
} }

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
struct xtvec_base;
namespace a8 namespace a8
{ {
typedef std::function<void(int, const a8::Args*)> TimerCb; typedef std::function<void(int, const a8::Args*)> TimerCb;
@ -16,16 +15,17 @@ namespace a8
void Init(XGetTickCountFunc func, void* context, int gc_time, int cache_timer_num); void Init(XGetTickCountFunc func, void* context, int gc_time, int cache_timer_num);
void Update(); void Update();
void SetTimeout(int time, TimerCb cb); inline void SetTimeout(int time, TimerCb cb);
void SetTimeoutEx(int time, TimerCb cb, Attacher* attacher); inline void SetTimeoutEx(int time, TimerCb cb, Attacher* attacher);
XTimerWp SetTimeoutWp(int time, TimerCb cb); inline XTimerWp SetTimeoutWp(int time, TimerCb cb);
XTimerWp SetTimeoutWpEx(int time, TimerCb cb, Attacher* attacher); inline XTimerWp SetTimeoutWpEx(int time, TimerCb cb, Attacher* attacher);
void SetInterval(int time, a8::TimerCb cb);
void SetIntervalEx(int time, a8::TimerCb cb, Attacher* attacher);
XTimerWp SetIntervalWp(int time, TimerCb cb);
XTimerWp SetIntervalWpEx(int time, TimerCb cb, Attacher* attacher);
void FireEvent(XTimerWp& timer_wp, a8::Args& args); inline void SetInterval(int time, a8::TimerCb cb);
inline void SetIntervalEx(int time, a8::TimerCb cb, Attacher* attacher);
inline XTimerWp SetIntervalWp(int time, TimerCb cb);
inline XTimerWp SetIntervalWpEx(int time, TimerCb cb, Attacher* attacher);
void FireEvent(XTimerWp& timer_wp, a8::Args* args);
void ModifyTime(XTimerWp& timer_wp, int expire_time); void ModifyTime(XTimerWp& timer_wp, int expire_time);
void Delete(XTimerWp& timer_wp); void Delete(XTimerWp& timer_wp);
long long GetRemainTime(XTimerWp& timer_wp); long long GetRemainTime(XTimerWp& timer_wp);
@ -33,15 +33,11 @@ namespace a8
bool IsRunning(); bool IsRunning();
private: private:
void UpdateTimer();
void ClearAttacher(Attacher* attacher); void ClearAttacher(Attacher* attacher);
void DestoryAttacher(Attacher* attacher); void DestoryAttacher(Attacher* attacher);
private: private:
xtvec_base* base_ = nullptr; class XTimerImpl* impl_ = nullptr;
XGetTickCountFunc get_tick_count_func_ = nullptr;
void* context_ = nullptr;
int gc_time_ = 10;
int cache_timer_num_ = 100;
friend class Attacher; friend class Attacher;
}; };