a6/Timer.java
aozhiwei 4e70850cd9 1
2019-12-16 21:29:29 +08:00

276 lines
8.8 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)
{
}
}
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 = new ListHead[TVR_SIZE];
private ListHead[] tv2 = new ListHead[TVN_SIZE];
private ListHead[] tv3 = new ListHead[TVN_SIZE];
private ListHead[] tv4 = new ListHead[TVN_SIZE];
private ListHead[] tv5 = new ListHead[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() {
}
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);
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_list, int expire_time) {
}
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_list) {
return 0;
}
public TimerList getRunningTimer() {
return runningTimer;
}
public int getIdleableMillSeconds() {
return 0;
}
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);
}
}