/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package java.util;
public final class TimerThread extends Thread
{
private static final Object LOCK;
static
{
LOCK = new Object();
}
private boolean terminated;
private int count;
private TimerTask[] queue;
private Object lock;
TimerThread()
{
super("Поток событий таймера");
this.queue = new TimerTask[16];
this.lock = new Object();
}
public void run()
{
boolean mustContinue;
boolean fixedRate;
TimerTask task;
Object monitor = lock;
do
{
waitTimer();
if(terminated)
{
break;
}
if((task = extract()) == null)
{
continue;
}
mustContinue = false;
synchronized(monitor)
{
label0:
{
fixedRate = task.fixedRate;
if(task.state != TimerTask.STATE_SCHEDULED)
{
task.owner = null;
mustContinue = true;
break label0;
}
task.shedExecutionTime = task.nextExecutionTime;
if(fixedRate)
{
task.nextExecutionTime = System.currentTimeMillis() + task.period;
}
task.state = TimerTask.STATE_EXECUTING;
}
}
if(mustContinue)
{
continue;
}
try
{
task.run();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
synchronized(monitor)
{
label0:
{
if(task.state != TimerTask.STATE_EXECUTING)
{
task.owner = null;
break label0;
}
if(!fixedRate)
{
task.nextExecutionTime = System.currentTimeMillis() + task.period;
}
if(task.periodic)
{
task.state = TimerTask.STATE_SCHEDULED;
pushTask(task);
} else
{
task.state = TimerTask.STATE_CANCELLED;
task.owner = null;
}
}
}
} while(true);
clear();
}
void terminate()
{
Object monitor;
synchronized(monitor = lock)
{
terminated = true;
monitor.notify();
}
}
void schedule(TimerTask task, long time)
{
int error;
Object monitor;
error = 0;
synchronized(LOCK)
{
label0:
{
if(task.state != TimerTask.STATE_FREE)
{
error = 1;
break label0;
}
task.periodic = false;
task.fixedRate = false;
task.state = TimerTask.STATE_SCHEDULED;
task.period = 0L;
}
}
if(error == 1)
{
throw new IllegalStateException("Timer.schedule: " +
"задача уже планировалась раннее.");
}
synchronized(monitor = lock)
{
task.nextExecutionTime = time;
task.owner = this;
pushTask(task);
monitor.notify();
}
}
void schedule(TimerTask task, long time, long period, boolean fixedRate)
{
int error;
Object monitor;
error = 0;
synchronized(LOCK)
{
label0:
{
if(task.state != TimerTask.STATE_FREE)
{
error = 1;
break label0;
}
task.periodic = true;
task.fixedRate = fixedRate;
task.state = TimerTask.STATE_SCHEDULED;
task.period = Math.max(0L, period);
}
}
if(error == 1)
{
throw new IllegalStateException(
(fixedRate ? "Timer.scheduleAtFixedRate" : "Timer.schedule").concat(": " +
"задача уже планировалась раннее."));
}
synchronized(monitor = lock)
{
task.nextExecutionTime = time;
task.owner = this;
pushTask(task);
monitor.notify();
}
}
boolean cancel(TimerTask task)
{
boolean result;
int index;
int count;
TimerTask[] queue;
Object monitor;
synchronized(monitor = lock)
{
label0:
{
if(task.owner != this)
{
result = false;
break label0;
}
result = task.periodic || task.state == TimerTask.STATE_SCHEDULED;
if((index = indexOf(task)) < 0)
{
task.state = TimerTask.STATE_CANCELLED;
break label0;
}
queue = this.queue;
if(index < (count = this.count) - 1)
{
Array.copy(queue, index + 1, queue, index, count - index - 1);
}
queue[this.count = count - 1] = null;
task.state = TimerTask.STATE_CANCELLED;
task.owner = null;
monitor.notify();
}
}
return result;
}
private void waitTimer()
{
int count;
long millis;
TimerTask[] queue;
Object monitor;
synchronized(monitor = this.lock)
{
do
{
count = this.count;
queue = this.queue;
try
{
if(count > 0 && (millis = queue[count - 1].nextExecutionTime -
System.currentTimeMillis()) > 0L)
{
monitor.wait(millis);
}
else if(count == 0)
{
monitor.wait();
}
break;
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
} while(true);
}
}
private void clear()
{
int i;
TimerTask[] queue = this.queue;
TimerTask task;
synchronized(lock)
{
for(i = count; i-- > 0; )
{
(task = queue[i]).state = TimerTask.STATE_CANCELLED;
task.owner = null;
queue[i] = null;
}
count = 0;
}
}
private void pushTask(TimerTask task)
{
int i;
int index;
int count;
long time;
TimerTask[] queue;
if((count = this.count) == (queue = this.queue).length)
{
Array.copy(queue, 0, queue = this.queue = new TimerTask[count << 1], 0, count);
}
time = task.nextExecutionTime;
index = count;
for(i = 0; i < count; i++)
{
if(queue[i].nextExecutionTime <= time)
{
index = i;
break;
}
}
if(index < count)
{
Array.copy(queue, index, queue, index + 1, count - index);
}
queue[index] = task;
this.count = count + 1;
}
private int indexOf(TimerTask task)
{
int i;
TimerTask[] queue = this.queue;
for(i = count; i-- > 0; )
{
if(queue[i] == task)
{
return i;
}
}
return -1;
}
private TimerTask extract()
{
int count;
TimerTask[] queue;
TimerTask result;
synchronized(lock)
{
if((count = this.count) > 0 &&
(result = (queue = this.queue)[count - 1]).nextExecutionTime <=
System.currentTimeMillis())
{
queue[this.count = count - 1] = null;
} else
{
result = null;
}
}
return result;
}
}