1
This commit is contained in:
commit
f85d842169
@ -69,6 +69,11 @@ namespace a8
|
||||
}
|
||||
p2++;
|
||||
}
|
||||
#if 0
|
||||
if (p2 > p1) {
|
||||
Add(p2 > p1 ? std::string(p1, p2 - p1) : "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string StringList::Text()
|
||||
|
@ -209,4 +209,10 @@ namespace a8
|
||||
return (int)(int64_val >> 32);
|
||||
}
|
||||
|
||||
float RandAngle()
|
||||
{
|
||||
float angle = 0.00001f + ((float)rand() / RAND_MAX) * 2.0f;
|
||||
return angle;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,6 +42,18 @@ namespace a8
|
||||
return t.back();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& Clamp(const T& v, const T& lo, const T& hi)
|
||||
{
|
||||
return v < hi ? (v > lo ? v : lo) : hi;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
float LengthSqr(const T& v)
|
||||
{
|
||||
return v.x * v.x + v.y * v.y;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SetToVector(std::set<T>& set_v, std::vector<T>& vector_v)
|
||||
{
|
||||
@ -73,6 +85,7 @@ namespace a8
|
||||
int Low32(long long int64_val);
|
||||
int High32(long long int64_val);
|
||||
|
||||
float RandAngle();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
32
a8/timer.cc
32
a8/timer.cc
@ -148,6 +148,9 @@ namespace a8
|
||||
|
||||
void Timer::UnInit()
|
||||
{
|
||||
Clear();
|
||||
delete base_;
|
||||
base_ = nullptr;
|
||||
}
|
||||
|
||||
void Timer::Update()
|
||||
@ -227,7 +230,7 @@ namespace a8
|
||||
if (!list_empty(&timer->attach_entry)) {
|
||||
list_del_init(&timer->attach_entry);
|
||||
}
|
||||
AddToFreeList(timer);
|
||||
AddToFreeList(timer);
|
||||
}
|
||||
|
||||
timer_list* Timer::GetTimerByAttach(list_head* attach_entry)
|
||||
@ -332,6 +335,33 @@ namespace a8
|
||||
base_->free_timer_num++;
|
||||
}
|
||||
|
||||
void Timer::Clear()
|
||||
{
|
||||
auto free_timers =
|
||||
[] (list_head* head)
|
||||
{
|
||||
while (!list_empty(head)) {
|
||||
struct timer_list *timer;
|
||||
timer = list_first_entry(head, struct timer_list,entry);
|
||||
DetachTimer(timer);
|
||||
if (!list_empty(&timer->attach_entry)) {
|
||||
list_del_init(&timer->attach_entry);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
void Timer::GC_TimerFunc(const a8::XParams& param)
|
||||
{
|
||||
Timer* timer = (Timer*)param.sender.GetUserData();
|
||||
|
@ -47,6 +47,7 @@ namespace a8
|
||||
void UpdateTimer();
|
||||
timer_list* NewTimerList();
|
||||
void AddToFreeList(timer_list* timer);
|
||||
void Clear();
|
||||
static void GC_TimerFunc(const a8::XParams& param);
|
||||
|
||||
private:
|
||||
|
@ -298,6 +298,33 @@ namespace a8
|
||||
return ReadFromJsonString(sl.Text());
|
||||
}
|
||||
|
||||
bool XObject::ReadFromJsonFile(const std::string& filename)
|
||||
{
|
||||
std::string json_data;
|
||||
{
|
||||
FILE *fp = fopen(filename.c_str(), "rb");
|
||||
if (!fp) {
|
||||
return false;
|
||||
}
|
||||
fseek(fp, 0, SEEK_END);
|
||||
int fileSize = ftell(fp);
|
||||
if(fileSize){
|
||||
char *p = (char*)malloc(fileSize + 1);
|
||||
if(p){
|
||||
*(p + fileSize) = '\0';
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fread(p, 1, fileSize, fp);
|
||||
if (fileSize > 0) {
|
||||
json_data.append(p, fileSize);
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
return ReadFromJsonString(json_data);
|
||||
}
|
||||
|
||||
bool XObject::ReadFromJsonString(const std::string& json_data)
|
||||
{
|
||||
Json::Reader reader;
|
||||
|
@ -44,6 +44,7 @@ namespace a8
|
||||
a8::XObject& Move(a8::XObject& a);
|
||||
|
||||
bool ReadFromFile(const std::string& filename);
|
||||
bool ReadFromJsonFile(const std::string& filename);
|
||||
bool ReadFromJsonString(const std::string& jsondata);
|
||||
bool ReadFromXmlFile(const std::string& filename);
|
||||
bool ReadFromXmlString(const std::string& xmldata);
|
||||
|
352
a8/xtimer.cc
Normal file
352
a8/xtimer.cc
Normal file
@ -0,0 +1,352 @@
|
||||
#include <a8/a8.h>
|
||||
|
||||
#include <a8/xtimer.h>
|
||||
|
||||
#define CONFIG_BASE_SMALL 0
|
||||
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
|
||||
#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
|
||||
#define TVN_SIZE (1 << TVN_BITS)
|
||||
#define TVR_SIZE (1 << TVR_BITS)
|
||||
#define TVN_MASK (TVN_SIZE - 1)
|
||||
#define TVR_MASK (TVR_SIZE - 1)
|
||||
#define INDEX(N) ((base->timer_tick >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
|
||||
|
||||
struct xtvec {
|
||||
struct list_head vec[TVN_SIZE];
|
||||
};
|
||||
|
||||
struct xtvec_root {
|
||||
struct list_head vec[TVR_SIZE];
|
||||
};
|
||||
|
||||
struct xtvec_base {
|
||||
struct xtimer_list *running_timer;
|
||||
long long timer_tick;
|
||||
list_head free_timer;
|
||||
int free_timer_num;
|
||||
struct xtvec_root tv1;
|
||||
struct xtvec tv2;
|
||||
struct xtvec tv3;
|
||||
struct xtvec tv4;
|
||||
struct xtvec tv5;
|
||||
};
|
||||
|
||||
struct xtimer_list {
|
||||
struct list_head entry;
|
||||
struct list_head attach_entry;
|
||||
int timer_type; // 0:deadline 1: repeattimer 2:fixedtimer outher:deadline
|
||||
long long expires;
|
||||
int expire_time;
|
||||
int fixed_timer_execute_times;
|
||||
struct xtvec_base *base;
|
||||
|
||||
a8::XTimerFunc timer_func;
|
||||
a8::XTimerAfterFunc timer_after_func;
|
||||
a8::XParams param;
|
||||
};
|
||||
|
||||
static void InternalAddXTimer(struct xtvec_base *base, struct xtimer_list *timer)
|
||||
{
|
||||
long long expires = timer->expires;
|
||||
long long idx = expires - base->timer_tick;
|
||||
struct list_head *vec;
|
||||
|
||||
if (idx < 0) {
|
||||
vec = base->tv1.vec + (base->timer_tick & TVR_MASK);
|
||||
}else if (idx < TVR_SIZE) {
|
||||
int i = expires & TVR_MASK;
|
||||
vec = base->tv1.vec + i;
|
||||
} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
|
||||
int i = (expires >> TVR_BITS) & TVN_MASK;
|
||||
vec = base->tv2.vec + i;
|
||||
} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
|
||||
int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
|
||||
vec = base->tv3.vec + i;
|
||||
} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
|
||||
int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
|
||||
vec = base->tv4.vec + i;
|
||||
} else {
|
||||
int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
|
||||
vec = base->tv5.vec + i;
|
||||
}
|
||||
list_add_tail(&timer->entry, vec);
|
||||
}
|
||||
|
||||
static int Cascade(struct xtvec_base *base, struct xtvec *tv, int index)
|
||||
{
|
||||
/* cascade all the timers from tv up one level */
|
||||
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::XParams& param,
|
||||
a8::XTimerFunc timer_func, a8::XTimerAfterFunc timer_after_func)
|
||||
{
|
||||
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->timer_func = timer_func;
|
||||
timer->timer_after_func = timer_after_func;
|
||||
timer->param = param;
|
||||
}
|
||||
|
||||
namespace a8
|
||||
{
|
||||
|
||||
XTimer::XTimer()
|
||||
{
|
||||
base_ = new xtvec_base();
|
||||
base_->running_timer = nullptr;
|
||||
base_->timer_tick = get_tick_count_func_(context_);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
XTimer::~XTimer()
|
||||
{
|
||||
Clear();
|
||||
delete base_;
|
||||
base_ = nullptr;
|
||||
}
|
||||
|
||||
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;
|
||||
AddRepeatTimer(gc_time_,
|
||||
a8::XParams().SetSender(this),
|
||||
&XTimer::GC_XTimerFunc);
|
||||
}
|
||||
|
||||
void XTimer::Update()
|
||||
{
|
||||
if (get_tick_count_func_(context_) >= base_->timer_tick) {
|
||||
UpdateTimer();
|
||||
}
|
||||
}
|
||||
|
||||
xtimer_list* XTimer::AddDeadLineTimer(int expire_time, a8::XParams param, a8::XTimerFunc timer_func,
|
||||
a8::XTimerAfterFunc timer_after_func)
|
||||
{
|
||||
xtimer_list *timer = NewTimerList();
|
||||
InitTimerList(base_,
|
||||
timer,
|
||||
0,
|
||||
get_tick_count_func_(context_) + expire_time,
|
||||
expire_time,
|
||||
param,
|
||||
timer_func,
|
||||
timer_after_func);
|
||||
ModifyTimer(timer, expire_time);
|
||||
return timer;
|
||||
}
|
||||
|
||||
xtimer_list* XTimer::AddDeadLineTimerAndAttach(int expire_time, a8::XParams param, a8::XTimerFunc timer_func,
|
||||
list_head* attach_list, a8::XTimerAfterFunc timer_after_func)
|
||||
{
|
||||
xtimer_list* timer = AddDeadLineTimer(expire_time, param, timer_func, timer_after_func);
|
||||
list_add_tail(&timer->attach_entry, attach_list);
|
||||
return timer;
|
||||
}
|
||||
|
||||
xtimer_list* XTimer::AddRepeatTimer(int expire_time, a8::XParams param, a8::XTimerFunc timer_func)
|
||||
{
|
||||
xtimer_list *timer = NewTimerList();
|
||||
InitTimerList(base_,
|
||||
timer,
|
||||
1,
|
||||
get_tick_count_func_(context_) + expire_time,
|
||||
expire_time,
|
||||
param,
|
||||
timer_func,
|
||||
nullptr);
|
||||
ModifyTimer(timer, expire_time);
|
||||
return timer;
|
||||
}
|
||||
|
||||
void XTimer::ModifyTimer(xtimer_list* timer, 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 XTimer::DeleteTimer(xtimer_list* timer)
|
||||
{
|
||||
if (timer->timer_after_func) {
|
||||
timer->timer_after_func(timer->param);
|
||||
}
|
||||
DetachTimer(timer);
|
||||
if (!list_empty(&timer->attach_entry)) {
|
||||
list_del_init(&timer->attach_entry);
|
||||
}
|
||||
AddToFreeList(timer);
|
||||
}
|
||||
|
||||
xtimer_list* XTimer::GetTimerByAttach(list_head* attach_entry)
|
||||
{
|
||||
if (attach_entry) {
|
||||
xtimer_list* timer = list_entry(attach_entry, struct xtimer_list, attach_entry);
|
||||
return timer;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
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->timer_func) {
|
||||
timer->timer_func(timer->param);
|
||||
}
|
||||
if (timer->timer_after_func) {
|
||||
timer->timer_after_func(timer->param);
|
||||
}
|
||||
switch (timer->timer_type) {
|
||||
case 1:
|
||||
case 2: //循环类定时 fixed timer也是循环定时器
|
||||
{
|
||||
if (timer->timer_type == 2) {
|
||||
timer->fixed_timer_execute_times++;
|
||||
}
|
||||
ModifyTimer(timer, timer->expire_time);
|
||||
}
|
||||
break;
|
||||
default: //deadline timer
|
||||
{
|
||||
DetachTimer(timer);
|
||||
if (!list_empty(&timer->attach_entry)) {
|
||||
list_del_init(&timer->attach_entry);
|
||||
}
|
||||
AddToFreeList(timer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
base->running_timer = nullptr;
|
||||
}
|
||||
|
||||
xtimer_list* XTimer::NewTimerList()
|
||||
{
|
||||
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 XTimer::AddToFreeList(xtimer_list* timer)
|
||||
{
|
||||
list_add_tail(&timer->entry, &base_->free_timer);
|
||||
base_->free_timer_num++;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
void XTimer::GC_XTimerFunc(const a8::XParams& param)
|
||||
{
|
||||
XTimer* timer = (XTimer*)param.sender.GetUserData();
|
||||
int i = 0;
|
||||
while (!list_empty(&timer->base_->free_timer) &&
|
||||
timer->base_->free_timer_num > timer->cache_timer_num_ && i < 1000) {
|
||||
xtimer_list* timer1 = list_first_entry(&timer->base_->free_timer, struct xtimer_list, entry);
|
||||
list_del_init(&timer1->entry);
|
||||
delete timer1;
|
||||
|
||||
timer->base_->free_timer_num--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
60
a8/xtimer.h
Normal file
60
a8/xtimer.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 仿照linux2.6内核定时器实现
|
||||
*/
|
||||
#ifndef A8_XTIMER_H
|
||||
#define A8_XTIMER_H
|
||||
|
||||
struct xtimer_list;
|
||||
struct xtvec_base;
|
||||
|
||||
namespace a8
|
||||
{
|
||||
typedef void (*XTimerFunc)(const a8::XParams& param);
|
||||
typedef void (*XTimerAfterFunc)(const a8::XParams& param);
|
||||
typedef long long (*XGetTickCountFunc)(void*);
|
||||
|
||||
class XTimer
|
||||
{
|
||||
private:
|
||||
XTimer();
|
||||
~XTimer();
|
||||
|
||||
public:
|
||||
void Init(XGetTickCountFunc func, void* context, int gc_time, int cache_timer_num);
|
||||
|
||||
void Update();
|
||||
|
||||
//添加截止时间定时器(一次性定时器)
|
||||
xtimer_list* AddDeadLineTimer(int expire_time, a8::XParams param, a8::XTimerFunc timer_func,
|
||||
a8::XTimerAfterFunc timer_after_func = nullptr);
|
||||
xtimer_list* AddDeadLineTimerAndAttach(int expire_time, a8::XParams,
|
||||
a8::XTimerFunc timer_func,
|
||||
list_head* attach_list,
|
||||
a8::XTimerAfterFunc timer_after_func = nullptr);
|
||||
//添加重复执行定时器(周期性定时器)
|
||||
xtimer_list* AddRepeatTimer(int expire_time, a8::XParams param, a8::XTimerFunc timer_func);
|
||||
//修改定时器参数
|
||||
void ModifyTimer(xtimer_list* timer, int expire_time);
|
||||
//删除定时器
|
||||
void DeleteTimer(xtimer_list* timer);
|
||||
//通过关联的list_head获取定时器对象
|
||||
xtimer_list* GetTimerByAttach(list_head* attach_entry);
|
||||
|
||||
private:
|
||||
void UpdateTimer();
|
||||
xtimer_list* NewTimerList();
|
||||
void AddToFreeList(xtimer_list* timer);
|
||||
void Clear();
|
||||
static void GC_XTimerFunc(const a8::XParams& param);
|
||||
|
||||
private:
|
||||
xtvec_base* base_ = nullptr;
|
||||
XGetTickCountFunc get_tick_count_func_ = nullptr;
|
||||
void* context_ = nullptr;
|
||||
int gc_time_ = 10;
|
||||
int cache_timer_num_ = 100;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user