summaryrefslogtreecommitdiff
path: root/java/src/IceInternal/Timer.java
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2007-08-31 17:01:34 +0200
committerBenoit Foucher <benoit@zeroc.com>2007-08-31 17:01:34 +0200
commit31efb365dfed25a2fdbe2e38178f7989cbfe00f4 (patch)
treeacf3bb92d51ae74ab897119d9334283db08c66aa /java/src/IceInternal/Timer.java
parentbug 2441 - Do not require IceBoc.ServiceManager.Endpoints to be set (diff)
downloadice-31efb365dfed25a2fdbe2e38178f7989cbfe00f4.tar.bz2
ice-31efb365dfed25a2fdbe2e38178f7989cbfe00f4.tar.xz
ice-31efb365dfed25a2fdbe2e38178f7989cbfe00f4.zip
Squashed commit of the following:
commit 1d43f88b9f7f1651ac367b217b10da3c9c5e7400 Author: Benoit Foucher <benoit@zeroc.com> Date: Fri Aug 31 16:55:20 2007 +0200 Added C# Timer implementation commit 52c3f88a429f62ed3564ab65c1af1736c2c1d2ee Author: Benoit Foucher <benoit@zeroc.com> Date: Fri Aug 31 14:49:18 2007 +0200 Added Java Timer impl.
Diffstat (limited to 'java/src/IceInternal/Timer.java')
-rw-r--r--java/src/IceInternal/Timer.java298
1 files changed, 298 insertions, 0 deletions
diff --git a/java/src/IceInternal/Timer.java b/java/src/IceInternal/Timer.java
new file mode 100644
index 00000000000..194eb5b072f
--- /dev/null
+++ b/java/src/IceInternal/Timer.java
@@ -0,0 +1,298 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+interface TimerTask
+{
+ void run();
+};
+
+public final class Timer extends Thread
+{
+ //
+ // Renamed from destroy to _destroy to avoid a deprecation warning caused
+ // by the destroy method inherited from Thread.
+ //
+ public void
+ _destroy()
+ {
+ synchronized(this)
+ {
+ if(_instance == null)
+ {
+ return;
+ }
+
+ _instance = null;
+ notify();
+
+ _tokens.clear();
+ _tasks.clear();
+ }
+
+ while(true)
+ {
+ try
+ {
+ join();
+ break;
+ }
+ catch(java.lang.InterruptedException ex)
+ {
+ }
+ }
+ }
+
+ synchronized public void
+ schedule(TimerTask task, long delay)
+ {
+ if(_instance == null)
+ {
+ return;
+ }
+
+ final Token token = new Token(System.currentTimeMillis() + delay, ++_tokenId, 0, task);
+
+ Object previous = _tasks.put(task, token);
+ assert previous == null;
+ _tokens.add(token);
+
+ if(token.scheduledTime < _wakeUpTime)
+ {
+ notify();
+ }
+ }
+
+ synchronized public void
+ scheduleRepeated(TimerTask task, long period)
+ {
+ if(_instance == null)
+ {
+ return;
+ }
+
+ final Token token = new Token(System.currentTimeMillis() + period, ++_tokenId, period, task);
+
+ Object previous = _tasks.put(task, token);
+ assert previous == null;
+ _tokens.add(token);
+
+ if(token.scheduledTime < _wakeUpTime)
+ {
+ notify();
+ }
+ }
+
+ synchronized public boolean
+ cancel(TimerTask task)
+ {
+ if(_instance == null)
+ {
+ return false;
+ }
+
+ Token token = (Token)_tasks.remove(task);
+ if(token == null)
+ {
+ return false;
+ }
+
+ _tokens.remove(token);
+ return true;
+ }
+
+ //
+ // Only for use by Instance.
+ //
+ Timer(IceInternal.Instance instance)
+ {
+ _instance = instance;
+
+ String threadName = _instance.initializationData().properties.getProperty("Ice.ProgramName");
+ if(threadName.length() > 0)
+ {
+ threadName += "-";
+ }
+ setName(threadName + "Ice.Timer");
+
+ start();
+ }
+
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtil.Assert.FinalizerAssert(_instance == null);
+
+ super.finalize();
+ }
+
+ public void
+ run()
+ {
+ Token token = null;
+ while(true)
+ {
+ synchronized(this)
+ {
+ if(_instance != null)
+ {
+ //
+ // If the task we just ran is a repeated task, schedule it
+ // again for executation if it wasn't canceled.
+ //
+ if(token != null && token.delay > 0)
+ {
+ if(_tasks.containsKey(token.task))
+ {
+ token.scheduledTime = System.currentTimeMillis() + token.delay;
+ _tokens.add(token);
+ }
+ }
+ }
+ token = null;
+
+ if(_instance == null)
+ {
+ break;
+ }
+
+ if(_tokens.isEmpty())
+ {
+ _wakeUpTime = Long.MAX_VALUE;
+ while(true)
+ {
+ try
+ {
+ wait();
+ break;
+ }
+ catch(java.lang.InterruptedException ex)
+ {
+ }
+ }
+ }
+
+ if(_instance == null)
+ {
+ break;
+ }
+
+ while(!_tokens.isEmpty() && _instance != null)
+ {
+ long now = System.currentTimeMillis();
+ Token first = (Token)_tokens.first();
+ if(first.scheduledTime <= now)
+ {
+ _tokens.remove(first);
+ token = first;
+ if(token.delay == 0)
+ {
+ _tasks.remove(token.task);
+ }
+ break;
+ }
+
+ _wakeUpTime = first.scheduledTime;
+ while(true)
+ {
+ try
+ {
+ wait(first.scheduledTime - now);
+ break;
+ }
+ catch(java.lang.InterruptedException ex)
+ {
+ }
+ }
+ }
+
+ if(_instance == null)
+ {
+ break;
+ }
+ }
+
+ if(token != null)
+ {
+ try
+ {
+ token.task.run();
+ }
+ catch(Exception ex)
+ {
+ synchronized(this)
+ {
+ if(_instance != null)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ String s = "unexpected exception from task run method in timer thread:\n" + sw.toString();
+ _instance.initializationData().logger.error(s);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static private class Token implements Comparable
+ {
+ public
+ Token(long scheduledTime, int id, long delay, TimerTask task)
+ {
+ this.scheduledTime = scheduledTime;
+ this.id = id;
+ this.delay = delay;
+ this.task = task;
+ }
+
+ public int
+ compareTo(Object o)
+ {
+ //
+ // Token are sorted by scheduled time and token id.
+ //
+ Token r = (Token)o;
+ if(scheduledTime < r.scheduledTime)
+ {
+ return -1;
+ }
+ else if(scheduledTime > r.scheduledTime)
+ {
+ return 1;
+ }
+
+ if(id < r.id)
+ {
+ return -1;
+ }
+ else if(id > r.id)
+ {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ long scheduledTime;
+ int id; // Since we can't compare references, we need to use another id.
+ long delay;
+ TimerTask task;
+ }
+
+ private final java.util.SortedSet _tokens = new java.util.TreeSet();
+ private final java.util.Map _tasks = new java.util.HashMap();
+ private Instance _instance;
+ private long _wakeUpTime = Long.MAX_VALUE;
+ private int _tokenId = 0;
+}