1
This commit is contained in:
parent
2964212b5f
commit
ffcbe9e7bf
832
a8/xtimer.cc
832
a8/xtimer.cc
@ -2,8 +2,6 @@
|
||||
|
||||
#include <a8/xtimer.h>
|
||||
|
||||
typedef struct list_head XTimerDestoryHandle;
|
||||
|
||||
#define CONFIG_BASE_SMALL 0
|
||||
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
|
||||
#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
|
||||
@ -46,12 +44,6 @@ struct xtimer_list {
|
||||
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)
|
||||
{
|
||||
long long expires = timer->expires;
|
||||
@ -85,500 +77,522 @@ static int Cascade(struct xtvec_base *base, struct xtvec *tv, int index)
|
||||
struct xtimer_list *timer, *tmp;
|
||||
struct list_head tv_list;
|
||||
|
||||
// 将tv数组中以index为下标的定时器队列取出,准备搬移
|
||||
list_replace_init(tv->vec + index, &tv_list);
|
||||
|
||||
// 根据超时时间,将队列中的定时器重新排队。定时器往上一级时间轮排队的过程就 // 在这里发生。
|
||||
list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
|
||||
InternalAddXTimer(base, timer);
|
||||
}
|
||||
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
|
||||
{
|
||||
typedef struct list_head XTimerDestoryHandle;
|
||||
|
||||
struct XTimerPtr
|
||||
{
|
||||
xtimer_list* timer = nullptr;
|
||||
};
|
||||
|
||||
struct XTimerDestoryHandleNode
|
||||
{
|
||||
struct list_head entry;
|
||||
std::function<void(xtimer_list*)> cb;
|
||||
};
|
||||
|
||||
class XTimerImpl
|
||||
{
|
||||
public:
|
||||
|
||||
XTimerImpl()
|
||||
{
|
||||
base_ = new xtvec_base();
|
||||
base_->running_timer = nullptr;
|
||||
INIT_LIST_HEAD(&base_->free_timer);
|
||||
base_->free_timer_num = 0;
|
||||
for (int j = 0; j < TVN_SIZE; j++) {
|
||||
INIT_LIST_HEAD(base_->tv5.vec + j);
|
||||
INIT_LIST_HEAD(base_->tv4.vec + j);
|
||||
INIT_LIST_HEAD(base_->tv3.vec + j);
|
||||
INIT_LIST_HEAD(base_->tv2.vec + j);
|
||||
}
|
||||
for (int j = 0; j < TVR_SIZE; j++) {
|
||||
INIT_LIST_HEAD(base_->tv1.vec + j);
|
||||
}
|
||||
}
|
||||
|
||||
~XTimerImpl()
|
||||
{
|
||||
#if 0
|
||||
Clear();
|
||||
#endif
|
||||
A8_SAFE_DELETE(base_);
|
||||
}
|
||||
|
||||
void Init(XGetTickCountFunc func, void* context, int gc_time, int cache_timer_num)
|
||||
{
|
||||
get_tick_count_func_ = func;
|
||||
context_ = context;
|
||||
gc_time_ = gc_time;
|
||||
cache_timer_num_ = cache_timer_num;
|
||||
base_->timer_tick = get_tick_count_func_(context_);
|
||||
SetInterval
|
||||
(gc_time_,
|
||||
[this] (int event, const a8::Args* args)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
int i = 0;
|
||||
while (!list_empty(&base_->free_timer) &&
|
||||
base_->free_timer_num > cache_timer_num_ && i < 1000) {
|
||||
xtimer_list* timer = list_first_entry(&base_->free_timer, struct xtimer_list, entry);
|
||||
list_del_init(&timer->entry);
|
||||
delete timer;
|
||||
|
||||
base_->free_timer_num--;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (get_tick_count_func_(context_) >= base_->timer_tick) {
|
||||
UpdateTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void InternalSetTimeout(int time, TimerCb cb, Attacher* attacher, XTimerWp* wp)
|
||||
{
|
||||
xtimer_list *timer = ::NewTimerList(base_);
|
||||
InitTimerList(base_,
|
||||
timer,
|
||||
0,
|
||||
get_tick_count_func_(context_) + expire_time,
|
||||
expire_time,
|
||||
timer_cb
|
||||
);
|
||||
ModifyTimerTimer(timer, expire_time);
|
||||
|
||||
#if 0
|
||||
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
|
||||
}
|
||||
|
||||
void InternalSetInterval(int time, TimerCb cb, Attacher* attacher, XTimerWp* wp)
|
||||
{
|
||||
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::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;
|
||||
}
|
||||
|
||||
void FireEvent(XTimerWp& timer_wp, a8::Args* args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ModifyTime(XTimerWp& timer_wp, int expire_time)
|
||||
{
|
||||
DetachTimer(timer);
|
||||
timer->expire_time = expire_time;
|
||||
if (timer->timer_type == 2) {
|
||||
long long tick = get_tick_count_func(context_);
|
||||
long long today_passed_seconds = time(nullptr) - a8::GetDaySeconds(time(nullptr), 0);
|
||||
timer->expires = (tick - today_passed_seconds * 1000) + expire_time;
|
||||
if (timer->fixed_timer_execute_times > 0) {
|
||||
if (timer->expires <= tick) { //已过期
|
||||
timer->expires += 1000 * 3600 * 24;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
timer->expires = get_tick_count_func_(context_) + expire_time;
|
||||
}
|
||||
InternalAddXTimer(base_, timer);
|
||||
}
|
||||
|
||||
void Delete(XTimerWp& timer_wp)
|
||||
{
|
||||
xtimer_list* timer = timer_ptr.lock()->timer;
|
||||
if (!timer) {
|
||||
abort();
|
||||
}
|
||||
if (base_->running_timer == timer) {
|
||||
base_->running_timer = nullptr;
|
||||
}
|
||||
if (timer->cb) {
|
||||
timer->cb(TIMER_DELETE_EVENT, nullptr);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
long long GetRemainTime(XTimerWp& timer_wp)
|
||||
{
|
||||
xtimer_list* timer = timer_ptr.lock()->timer;
|
||||
if (!timer) {
|
||||
abort();
|
||||
}
|
||||
long long remain_time = timer->expires - get_tick_count_func_(context_);
|
||||
return std::max(remain_time, (long long)0);
|
||||
}
|
||||
|
||||
bool IsRunning()
|
||||
{
|
||||
return base_->running_timer != nullptr;
|
||||
}
|
||||
|
||||
void ClearAttacher(Attacher* attacher)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DestoryAttacher(Attacher* attacher)
|
||||
{
|
||||
#if 0
|
||||
xtimer_list* timer = timer_ptr.lock()->timer;
|
||||
if (!timer) {
|
||||
abort();
|
||||
}
|
||||
if (base_->running_timer == timer) {
|
||||
base_->running_timer = nullptr;
|
||||
}
|
||||
if (timer->cb) {
|
||||
timer->cb(TIMER_DESTORY_EVNET, nullptr);
|
||||
}
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 DeleteCurrentTimer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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 =
|
||||
[] (list_head* head)
|
||||
{
|
||||
while (!list_empty(head)) {
|
||||
struct xtimer_list *timer;
|
||||
timer = list_first_entry(head, struct xtimer_list,entry);
|
||||
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;
|
||||
}
|
||||
delete timer;
|
||||
}
|
||||
};
|
||||
for (int j = 0; j < TVN_SIZE; j++) {
|
||||
free_timers(base_->tv5.vec + j);
|
||||
free_timers(base_->tv4.vec + j);
|
||||
free_timers(base_->tv3.vec + j);
|
||||
free_timers(base_->tv2.vec + j);
|
||||
}
|
||||
for (int j = 0; j < TVR_SIZE; j++) {
|
||||
free_timers(base_->tv1.vec + j);
|
||||
}
|
||||
free_timers(&base_->free_timer);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
base_ = new xtvec_base();
|
||||
base_->running_timer = nullptr;
|
||||
INIT_LIST_HEAD(&base_->free_timer);
|
||||
base_->free_timer_num = 0;
|
||||
for (int j = 0; j < TVN_SIZE; j++) {
|
||||
INIT_LIST_HEAD(base_->tv5.vec + j);
|
||||
INIT_LIST_HEAD(base_->tv4.vec + j);
|
||||
INIT_LIST_HEAD(base_->tv3.vec + j);
|
||||
INIT_LIST_HEAD(base_->tv2.vec + j);
|
||||
}
|
||||
for (int j = 0; j < TVR_SIZE; j++) {
|
||||
INIT_LIST_HEAD(base_->tv1.vec + j);
|
||||
}
|
||||
impl_ = new XTimerImpl();
|
||||
}
|
||||
|
||||
XTimer::~XTimer()
|
||||
{
|
||||
#if 0
|
||||
Clear();
|
||||
#endif
|
||||
delete base_;
|
||||
base_ = nullptr;
|
||||
A8_SAFE_DELETE(impl_);
|
||||
}
|
||||
|
||||
void XTimer::Init(XGetTickCountFunc func, void* context, int gc_time, int cache_timer_num)
|
||||
{
|
||||
get_tick_count_func_ = func;
|
||||
context_ = context;
|
||||
gc_time_ = gc_time;
|
||||
cache_timer_num_ = cache_timer_num;
|
||||
base_->timer_tick = get_tick_count_func_(context_);
|
||||
SetInterval
|
||||
(gc_time_,
|
||||
[this] (int event, const a8::Args* args)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
int i = 0;
|
||||
while (!list_empty(&base_->free_timer) &&
|
||||
base_->free_timer_num > cache_timer_num_ && i < 1000) {
|
||||
xtimer_list* timer = list_first_entry(&base_->free_timer, struct xtimer_list, entry);
|
||||
list_del_init(&timer->entry);
|
||||
delete timer;
|
||||
|
||||
base_->free_timer_num--;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
});
|
||||
impl_->Init(func, context, gc_time, cache_timer_num);
|
||||
}
|
||||
|
||||
void XTimer::Update()
|
||||
{
|
||||
if (get_tick_count_func_(context_) >= base_->timer_tick) {
|
||||
UpdateTimer();
|
||||
}
|
||||
impl_->Update();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void XTimer::AddDeadLineTimer(
|
||||
int expire_time,
|
||||
a8::TimerCbProc timer_cb,
|
||||
a8::XTimerAttacher* attacher
|
||||
)
|
||||
{
|
||||
xtimer_list *timer = ::NewTimerList(base_);
|
||||
InitTimerList(base_,
|
||||
timer,
|
||||
0,
|
||||
get_tick_count_func_(context_) + expire_time,
|
||||
expire_time,
|
||||
timer_cb
|
||||
);
|
||||
#if 0
|
||||
ModifyTimer(timer, expire_time);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::weak_ptr<XTimerPtr> XTimer::AddDeadLineTimerEx(
|
||||
int expire_time,
|
||||
a8::TimerCbProc timer_cb,
|
||||
a8::XTimerAttacher* attacher
|
||||
)
|
||||
{
|
||||
xtimer_list *timer = ::NewTimerList(base_);
|
||||
InitTimerList(base_,
|
||||
timer,
|
||||
0,
|
||||
get_tick_count_func_(context_) + expire_time,
|
||||
expire_time,
|
||||
timer_cb
|
||||
);
|
||||
#if 0
|
||||
ModifyTimer(timer, expire_time);
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void XTimer::AddRepeatTimer(
|
||||
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 XTimer::ModifyTimer(std::weak_ptr<XTimerPtr>& timer_ptr, int expire_time)
|
||||
{
|
||||
xtimer_list* timer = timer_ptr.lock()->timer;
|
||||
DetachTimer(timer);
|
||||
timer->expire_time = expire_time;
|
||||
if (timer->timer_type == 2) {
|
||||
long long tick = get_tick_count_func_(context_);
|
||||
long long today_passed_seconds = time(nullptr) - a8::GetDaySeconds(time(nullptr), 0);
|
||||
timer->expires = (tick - today_passed_seconds * 1000) + expire_time;
|
||||
if (timer->fixed_timer_execute_times > 0) {
|
||||
if (timer->expires <= tick) { //已过期
|
||||
timer->expires += 1000 * 3600 * 24;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
timer->expires = get_tick_count_func_(context_) + expire_time;
|
||||
}
|
||||
InternalAddXTimer(base_, timer);
|
||||
}
|
||||
|
||||
void XTimer::DeleteTimer(std::weak_ptr<XTimerPtr>& timer_ptr)
|
||||
{
|
||||
xtimer_list* timer = timer_ptr.lock()->timer;
|
||||
if (!timer) {
|
||||
abort();
|
||||
}
|
||||
if (base_->running_timer == timer) {
|
||||
base_->running_timer = nullptr;
|
||||
}
|
||||
if (timer->cb) {
|
||||
timer->cb(TIMER_DELETE_EVENT, nullptr);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
long long XTimer::GetRemainTime(std::weak_ptr<XTimerPtr>& timer_ptr)
|
||||
{
|
||||
xtimer_list* timer = timer_ptr.lock()->timer;
|
||||
if (!timer) {
|
||||
abort();
|
||||
}
|
||||
long long remain_time = timer->expires - get_tick_count_func_(context_);
|
||||
return std::max(remain_time, (long long)0);
|
||||
}
|
||||
|
||||
void XTimer::DestoryTimer(std::weak_ptr<XTimerPtr>& timer_ptr)
|
||||
{
|
||||
xtimer_list* timer = timer_ptr.lock()->timer;
|
||||
if (!timer) {
|
||||
abort();
|
||||
}
|
||||
if (base_->running_timer == timer) {
|
||||
base_->running_timer = nullptr;
|
||||
}
|
||||
if (timer->cb) {
|
||||
timer->cb(TIMER_DESTORY_EVNET, nullptr);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
xtimer_list* XTimer::GetTimerByAttach(list_head* attach_entry)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
xtimer_list* XTimer::GetRunningTimer()
|
||||
{
|
||||
return base_->running_timer;
|
||||
}
|
||||
|
||||
XTimerDestoryHandle* XTimer::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 XTimer::RemoveTimerDestoryHandle(XTimerDestoryHandle* handle)
|
||||
{
|
||||
if (!handle || list_empty(handle)) {
|
||||
abort();
|
||||
}
|
||||
|
||||
XTimerDestoryHandleNode* node = list_entry(handle, XTimerDestoryHandleNode, entry);
|
||||
list_del_init(&node->entry);
|
||||
delete node;
|
||||
}
|
||||
|
||||
bool XTimer::IsRunningTimer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void XTimer::Clear()
|
||||
{
|
||||
auto free_timers =
|
||||
[] (list_head* head)
|
||||
{
|
||||
while (!list_empty(head)) {
|
||||
struct xtimer_list *timer;
|
||||
timer = list_first_entry(head, struct xtimer_list,entry);
|
||||
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;
|
||||
}
|
||||
delete timer;
|
||||
}
|
||||
};
|
||||
for (int j = 0; j < TVN_SIZE; j++) {
|
||||
free_timers(base_->tv5.vec + j);
|
||||
free_timers(base_->tv4.vec + j);
|
||||
free_timers(base_->tv3.vec + j);
|
||||
free_timers(base_->tv2.vec + j);
|
||||
}
|
||||
for (int j = 0; j < TVR_SIZE; j++) {
|
||||
free_timers(base_->tv1.vec + j);
|
||||
}
|
||||
free_timers(&base_->free_timer);
|
||||
}
|
||||
|
||||
#endif
|
||||
void XTimer::SetTimeout(int time, TimerCb cb)
|
||||
{
|
||||
|
||||
impl_->InternalSetTimeout(time, cb, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void XTimer::SetTimeoutEx(int time, TimerCb cb, Attacher* attacher)
|
||||
{
|
||||
|
||||
impl_->InternalSetTimeout(time, cb, attacher, nullptr);
|
||||
}
|
||||
|
||||
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 result;
|
||||
impl_->InternalSetTimeout(time, cb, attacherk, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void XTimer::SetInterval(int time, a8::TimerCb cb)
|
||||
{
|
||||
|
||||
impl_->InternalSetInterval(time, cb, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void XTimer::SetIntervalEx(int time, a8::TimerCb cb, Attacher* attacher)
|
||||
{
|
||||
|
||||
impl_->InternalSetInterval(time, cb, attacker, nullptr);
|
||||
}
|
||||
|
||||
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 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)
|
||||
{
|
||||
|
||||
impl_->ModifyTime(timr_wp, expire_time);
|
||||
}
|
||||
|
||||
void XTimer::Delete(XTimerWp& timer_wp)
|
||||
{
|
||||
|
||||
impl_->Delete(timer_wp);
|
||||
}
|
||||
|
||||
long long XTimer::GetRemainTime(XTimerWp& timer_wp)
|
||||
{
|
||||
|
||||
return impl_->GetRemainTime(timer_wp);
|
||||
}
|
||||
|
||||
bool XTimer::IsRunning()
|
||||
{
|
||||
|
||||
return impl_->IsRunning();
|
||||
}
|
||||
|
||||
void XTimer::ClearAttacher(Attacher* attacher)
|
||||
{
|
||||
|
||||
impl_->ClearAttacher(attacher);
|
||||
}
|
||||
|
||||
void XTimer::DestoryAttacher(Attacher* 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;
|
||||
impl_->DestoryAttacher(attacher);
|
||||
}
|
||||
|
||||
void XTimer::DeleteCurrentTimer()
|
||||
{
|
||||
|
||||
impl_->DeleteCurrentTimer();
|
||||
}
|
||||
|
||||
}
|
||||
|
28
a8/xtimer.h
28
a8/xtimer.h
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
struct xtvec_base;
|
||||
namespace a8
|
||||
{
|
||||
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 Update();
|
||||
|
||||
void SetTimeout(int time, TimerCb cb);
|
||||
void SetTimeoutEx(int time, TimerCb cb, Attacher* attacher);
|
||||
XTimerWp SetTimeoutWp(int time, TimerCb cb);
|
||||
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);
|
||||
inline void SetTimeout(int time, TimerCb cb);
|
||||
inline void SetTimeoutEx(int time, TimerCb cb, Attacher* attacher);
|
||||
inline XTimerWp SetTimeoutWp(int time, TimerCb cb);
|
||||
inline XTimerWp SetTimeoutWpEx(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 Delete(XTimerWp& timer_wp);
|
||||
long long GetRemainTime(XTimerWp& timer_wp);
|
||||
@ -33,15 +33,11 @@ namespace a8
|
||||
bool IsRunning();
|
||||
|
||||
private:
|
||||
void UpdateTimer();
|
||||
void ClearAttacher(Attacher* attacher);
|
||||
void DestoryAttacher(Attacher* attacher);
|
||||
|
||||
private:
|
||||
xtvec_base* base_ = nullptr;
|
||||
XGetTickCountFunc get_tick_count_func_ = nullptr;
|
||||
void* context_ = nullptr;
|
||||
int gc_time_ = 10;
|
||||
int cache_timer_num_ = 100;
|
||||
class XTimerImpl* impl_ = nullptr;
|
||||
|
||||
friend class Attacher;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user