305 lines
10 KiB
Java
305 lines
10 KiB
Java
package a6;
|
|
|
|
public class Timer {
|
|
|
|
@FunctionalInterface
|
|
public interface ITimerFunc
|
|
{
|
|
public void OnTimer(XParams param);
|
|
}
|
|
|
|
@FunctionalInterface
|
|
public interface ITimerAfterFunc
|
|
{
|
|
public void OnTimerAfter(XParams param);
|
|
}
|
|
|
|
@FunctionalInterface
|
|
public interface IGetTickCountFunc
|
|
{
|
|
public long GetTickCount(Object context);
|
|
}
|
|
|
|
private enum TimerType
|
|
{
|
|
DEADLINE,
|
|
REPEAT,
|
|
FIXED
|
|
}
|
|
|
|
public class TimerList
|
|
{
|
|
private ListHead entry = new ListHead();
|
|
private ListHead attachEntry;
|
|
private TimerType timerType = TimerType.DEADLINE;
|
|
private int milli_seconds = 0;
|
|
private long expires = 0;
|
|
private int fixedTimerExecuteTimes = 0;
|
|
|
|
private ITimerFunc timerFunc;
|
|
private ITimerAfterFunc timerAfterFunc;
|
|
private XParams param;
|
|
|
|
private void initTimerList(Timer timer, TimerType timer_type, int milli_seconds,
|
|
XParams param, ITimerFunc timerFunc, ITimerAfterFunc afterFunc)
|
|
{
|
|
this.timerType = timer_type;
|
|
this.expires = timer.getTickCount.GetTickCount(timer.content) + milli_seconds;
|
|
this.milli_seconds = milli_seconds;
|
|
this.fixedTimerExecuteTimes = 0;
|
|
this.timerFunc = timerFunc;
|
|
this.timerAfterFunc = afterFunc;
|
|
this.param = param;
|
|
}
|
|
}
|
|
|
|
private static final boolean CONFIG_BASE_SMALL = false;
|
|
private static final int TVN_BITS = CONFIG_BASE_SMALL ? 4 : 6;
|
|
private static final int TVR_BITS = CONFIG_BASE_SMALL ? 6 : 8;
|
|
private static final int TVN_SIZE = 1 << TVN_BITS;
|
|
private static final int TVR_SIZE = 1 << TVR_BITS;
|
|
private static final int TVN_MASK = TVN_SIZE - 1;
|
|
private static final int TVR_MASK = TVR_SIZE - 1;
|
|
|
|
private int freeTimerNum = 0;
|
|
private ListHead freeTimer = new ListHead();
|
|
private TimerList runningTimer;
|
|
private long timerTick = 0;
|
|
private IGetTickCountFunc getTickCount;
|
|
private Object content;
|
|
private int gcTime = 0;
|
|
private int cacheTimerNum = 0;
|
|
private ListHead[] tv1 = SysUtils.newArray(ListHead.class, TVR_SIZE);
|
|
private ListHead[] tv2 = SysUtils.newArray(ListHead.class, TVN_SIZE);
|
|
private ListHead[] tv3 = SysUtils.newArray(ListHead.class, TVN_SIZE);
|
|
private ListHead[] tv4 = SysUtils.newArray(ListHead.class, TVN_SIZE);
|
|
private ListHead[] tv5 = SysUtils.newArray(ListHead.class, TVN_SIZE);
|
|
private ListHead workList = new ListHead();
|
|
private ListHead cascadeList = new ListHead();
|
|
|
|
public void init(IGetTickCountFunc func, Object content, int gc_time, int cache_timer_num) {
|
|
this.getTickCount = func;
|
|
this.content = content;
|
|
this.gcTime = gc_time;
|
|
this.cacheTimerNum = cache_timer_num;
|
|
}
|
|
|
|
public void unInit() {
|
|
clear();
|
|
}
|
|
|
|
public void update() {
|
|
while (getTickCount.GetTickCount(content) >= timerTick) {
|
|
int index = (int)(timerTick & TVR_MASK);
|
|
|
|
if (index == 0 &&
|
|
cascade(tv2, getTimerIndex(index)) == 0 &&
|
|
cascade(tv3, getTimerIndex(index)) == 0 &&
|
|
cascade(tv4, getTimerIndex(index)) == 0
|
|
) {
|
|
cascade(tv5, getTimerIndex(index));
|
|
}
|
|
|
|
++timerTick;
|
|
tv1[index].replaceInit(workList);
|
|
while (!workList.empty()) {
|
|
TimerList timer = (TimerList)workList.firstEntry();
|
|
runningTimer = timer;
|
|
if (timer.timerFunc != null) {
|
|
timer.timerFunc.OnTimer(timer.param);
|
|
}
|
|
if (timer.timerAfterFunc != null) {
|
|
timer.timerAfterFunc.OnTimerAfter(timer.param);
|
|
}
|
|
if (runningTimer != null) {
|
|
switch (runningTimer.timerType) {
|
|
case REPEAT:
|
|
case FIXED:
|
|
{
|
|
if (timer.timerType == TimerType.FIXED) {
|
|
++timer.fixedTimerExecuteTimes;
|
|
}
|
|
modifyTimer(timer, timer.milli_seconds);
|
|
}
|
|
break;
|
|
case DEADLINE:
|
|
{
|
|
detachTimer(timer);
|
|
if (timer.attachEntry != null && !timer.attachEntry.empty()) {
|
|
timer.attachEntry.delInit();
|
|
}
|
|
addToFreeList(timer);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
runningTimer = null;
|
|
}
|
|
|
|
public TimerList addDeadLineTimer(int expire_time, XParams param, ITimerFunc timer_func) {
|
|
return addDeadLineTimer(expire_time, param, timer_func, null);
|
|
}
|
|
|
|
public TimerList addDeadLineTimer(int expire_time, XParams param, ITimerFunc timer_func,
|
|
ITimerAfterFunc after_func) {
|
|
TimerList timer = newTimerList();
|
|
timer.initTimerList(this, TimerType.DEADLINE, expire_time, param, timer_func, after_func);
|
|
modifyTimer(timer, expire_time);
|
|
return timer;
|
|
}
|
|
|
|
public TimerList addDeadLineTimerAndAttach(int expire_time, XParams param, ITimerFunc timer_func,
|
|
TimerAttacher timer_attacher) {
|
|
return addDeadLineTimerAndAttach(expire_time, param, timer_func, timer_attacher, null);
|
|
}
|
|
|
|
public TimerList addDeadLineTimerAndAttach(int expire_time, XParams param, ITimerFunc timer_func,
|
|
TimerAttacher timer_attacher, ITimerAfterFunc after_func) {
|
|
TimerList timer = addDeadLineTimer(expire_time, param, timer_func, after_func);
|
|
timer_attacher.addTimer(timer.attachEntry);
|
|
return timer;
|
|
}
|
|
|
|
public TimerList addRepeatTimer(int expire_time, XParams param, ITimerFunc timer_func) {
|
|
TimerList timer = newTimerList();
|
|
timer.initTimerList(this, TimerType.REPEAT, expire_time, param, timer_func, null);
|
|
modifyTimer(timer, expire_time);
|
|
return timer;
|
|
}
|
|
|
|
public TimerList addFixedTimer(int expire_time, XParams param, ITimerFunc timer_func) {
|
|
TimerList timer = newTimerList();
|
|
timer.initTimerList(this, TimerType.FIXED, expire_time, param, timer_func, null);
|
|
modifyTimer(timer, expire_time);
|
|
return timer;
|
|
}
|
|
|
|
public void modifyTimer(TimerList timer, int expire_time) {
|
|
detachTimer(timer);
|
|
if (timer.timerType == TimerType.FIXED) {
|
|
long tick = System.currentTimeMillis();
|
|
int today_passed_seconds = SysUtils.now() - SysUtils.getDaySeconds(SysUtils.now(), 0);
|
|
timer.expires = (tick - today_passed_seconds * 1000) + expire_time;
|
|
if (timer.fixedTimerExecuteTimes > 0) {
|
|
if (timer.expires <= tick) {
|
|
timer.expires += 1000 * 3600 * 24;
|
|
}
|
|
} else {
|
|
timer.expires = getTickCount.GetTickCount(content) + expire_time;
|
|
}
|
|
}
|
|
timer.milli_seconds = expire_time;
|
|
internalAddTimer(timer);
|
|
}
|
|
|
|
public TimerList getTimerByAttach(ListHead attach_entry) {
|
|
return (TimerList)attach_entry.data;
|
|
}
|
|
|
|
public XParams getMutableParams(TimerList timer_list) {
|
|
return timer_list.param;
|
|
}
|
|
|
|
public long getRemainTime(TimerList timer) {
|
|
long remain_time = timer.expires - getTickCount.GetTickCount(content);
|
|
return remain_time;
|
|
}
|
|
|
|
public TimerList getRunningTimer() {
|
|
return runningTimer;
|
|
}
|
|
|
|
public int getIdleableMillSeconds() {
|
|
int idle_time = 1;
|
|
for (int lv1_idx = (int)(timerTick % TVR_MASK); lv1_idx < TVR_SIZE; ++lv1_idx) {
|
|
if (!tv1[lv1_idx].empty()){
|
|
return idle_time <= 1 ? 1 : idle_time - 1;
|
|
}
|
|
++idle_time;
|
|
}
|
|
return idle_time;
|
|
}
|
|
|
|
public void deleteTimer(TimerList timer_list) {
|
|
if (timer_list.timerAfterFunc != null) {
|
|
timer_list.timerAfterFunc.OnTimerAfter(timer_list.param);
|
|
}
|
|
detachTimer(timer_list);
|
|
if (timer_list.attachEntry != null && !timer_list.attachEntry.empty()) {
|
|
timer_list.attachEntry.del();
|
|
}
|
|
addToFreeList(timer_list);
|
|
}
|
|
|
|
public void detachTimer(TimerList timer_list) {
|
|
if (timer_list.entry != null && !timer_list.entry.empty()) {
|
|
timer_list.entry.delInit();
|
|
}
|
|
}
|
|
|
|
private TimerList newTimerList() {
|
|
return new TimerList();
|
|
}
|
|
|
|
private void clear() {
|
|
|
|
}
|
|
|
|
private void addToFreeList(TimerList timer_list) {
|
|
freeTimer.addTail(timer_list.entry);
|
|
++freeTimerNum;
|
|
}
|
|
|
|
private void gcTimerFunc() {
|
|
|
|
}
|
|
|
|
private int cascade(ListHead[] tv, int index) {
|
|
tv[index].replaceInit(cascadeList);
|
|
|
|
if (!cascadeList.empty()) {
|
|
ListHead pos, n;
|
|
for (pos = cascadeList.next, n = pos.next;
|
|
pos != cascadeList;
|
|
pos = n , n = pos.next) {
|
|
internalAddTimer((TimerList)pos.data);
|
|
}
|
|
}
|
|
cascadeList.init();
|
|
return index;
|
|
}
|
|
|
|
private final int getTimerIndex(int index) {
|
|
return (int)((timerTick >> (TVR_BITS + index * TVN_BITS)) & TVN_MASK);
|
|
}
|
|
|
|
private final void internalAddTimer(TimerList timer) {
|
|
long expires = timer.expires;
|
|
long idx = expires - timerTick;
|
|
ListHead vec;
|
|
|
|
if (idx < 0) {
|
|
vec = tv1[(int)(timerTick & TVR_MASK)];
|
|
} else if (idx < TVR_SIZE) {
|
|
int i = (int)(expires & TVR_MASK);
|
|
vec = tv1[i];
|
|
} else if (idx < (1 << (TVR_BITS + TVN_BITS))) {
|
|
int i = (int)(expires >> TVR_BITS) & TVN_MASK;
|
|
vec = tv2[i];
|
|
} else if (idx < (1 << (TVR_BITS + 2 * TVN_BITS))) {
|
|
int i = (int)(expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
|
|
vec = tv3[i];
|
|
} else if (idx < (1 << (TVR_BITS + 3 * TVN_BITS))) {
|
|
int i = (int)(expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
|
|
vec = tv4[i];
|
|
} else {
|
|
int i = (int)(expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
|
|
vec = tv5[i];
|
|
}
|
|
vec.addTail(vec);
|
|
}
|
|
|
|
}
|