1.1 --- a/rt/emul/compact/src/main/java/java/util/Timer.java Sat Nov 02 16:43:48 2013 +0100
1.2 +++ b/rt/emul/compact/src/main/java/java/util/Timer.java Sat Nov 02 21:09:52 2013 +0100
1.3 @@ -26,6 +26,7 @@
1.4 package java.util;
1.5 import java.util.Date;
1.6 import java.util.concurrent.atomic.AtomicInteger;
1.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.8
1.9 /**
1.10 * A facility for threads to schedule tasks for future execution in a
1.11 @@ -111,7 +112,7 @@
1.12 protected void finalize() throws Throwable {
1.13 synchronized(queue) {
1.14 thread.newTasksMayBeScheduled = false;
1.15 - queue.notify(); // In case queue is empty.
1.16 + thread.notifyQueue(1); // In case queue is empty.
1.17 }
1.18 }
1.19 };
1.20 @@ -156,8 +157,6 @@
1.21 * @since 1.5
1.22 */
1.23 public Timer(String name) {
1.24 - thread.setName(name);
1.25 - thread.start();
1.26 }
1.27
1.28 /**
1.29 @@ -171,9 +170,6 @@
1.30 * @since 1.5
1.31 */
1.32 public Timer(String name, boolean isDaemon) {
1.33 - thread.setName(name);
1.34 - thread.setDaemon(isDaemon);
1.35 - thread.start();
1.36 }
1.37
1.38 /**
1.39 @@ -407,7 +403,7 @@
1.40
1.41 queue.add(task);
1.42 if (queue.getMin() == task)
1.43 - queue.notify();
1.44 + thread.notifyQueue(1);
1.45 }
1.46 }
1.47
1.48 @@ -429,10 +425,10 @@
1.49 synchronized(queue) {
1.50 thread.newTasksMayBeScheduled = false;
1.51 queue.clear();
1.52 - queue.notify(); // In case queue was already empty.
1.53 + thread.notifyQueue(1); // In case queue was already empty.
1.54 }
1.55 }
1.56 -
1.57 +
1.58 /**
1.59 * Removes all cancelled tasks from this timer's task queue. <i>Calling
1.60 * this method has no effect on the behavior of the timer</i>, but
1.61 @@ -478,7 +474,7 @@
1.62 * reschedules repeating tasks, and removes cancelled tasks and spent
1.63 * non-repeating tasks from the queue.
1.64 */
1.65 -class TimerThread extends Thread {
1.66 +class TimerThread implements Runnable {
1.67 /**
1.68 * This flag is set to false by the reaper to inform us that there
1.69 * are no more live references to our Timer object. Once this flag
1.70 @@ -500,30 +496,41 @@
1.71 this.queue = queue;
1.72 }
1.73
1.74 + void notifyQueue(int delay) {
1.75 + if (delay < 1) {
1.76 + delay = 1;
1.77 + }
1.78 + setTimeout(delay, this);
1.79 + }
1.80 +
1.81 + @JavaScriptBody(args = { "delay", "r" }, body = "window.setTimeout(function() { r.run__V(); }, delay);")
1.82 + private static native void setTimeout(int delay, Runnable r);
1.83 +
1.84 public void run() {
1.85 - try {
1.86 - mainLoop();
1.87 - } finally {
1.88 - // Someone killed this Thread, behave as if Timer cancelled
1.89 - synchronized(queue) {
1.90 - newTasksMayBeScheduled = false;
1.91 - queue.clear(); // Eliminate obsolete references
1.92 - }
1.93 - }
1.94 + mainLoop(1);
1.95 +// try {
1.96 +// mainLoop(0);
1.97 +// } finally {
1.98 +// // Someone killed this Thread, behave as if Timer cancelled
1.99 +// synchronized(queue) {
1.100 +// newTasksMayBeScheduled = false;
1.101 +// queue.clear(); // Eliminate obsolete references
1.102 +// }
1.103 +// }
1.104 }
1.105
1.106 /**
1.107 * The main timer loop. (See class comment.)
1.108 */
1.109 - private void mainLoop() {
1.110 - while (true) {
1.111 + private void mainLoop(int inc) {
1.112 + for (int i = 0; i < 1; i += inc) {
1.113 try {
1.114 TimerTask task;
1.115 boolean taskFired;
1.116 synchronized(queue) {
1.117 // Wait for queue to become non-empty
1.118 while (queue.isEmpty() && newTasksMayBeScheduled)
1.119 - queue.wait();
1.120 + break;
1.121 if (queue.isEmpty())
1.122 break; // Queue is empty and will forever remain; die
1.123
1.124 @@ -548,12 +555,16 @@
1.125 }
1.126 }
1.127 }
1.128 - if (!taskFired) // Task hasn't yet fired; wait
1.129 - queue.wait(executionTime - currentTime);
1.130 + if (!taskFired) {
1.131 + // Task hasn't yet fired; wait
1.132 + notifyQueue((int)(executionTime - currentTime));
1.133 + return;
1.134 + }
1.135 }
1.136 if (taskFired) // Task fired; run it, holding no locks
1.137 task.run();
1.138 - } catch(InterruptedException e) {
1.139 + } catch(Exception e) {
1.140 + e.printStackTrace();
1.141 }
1.142 }
1.143 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/TimerTest.java Sat Nov 02 21:09:52 2013 +0100
2.3 @@ -0,0 +1,81 @@
2.4 +/**
2.5 + * Back 2 Browser Bytecode Translator
2.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.7 + *
2.8 + * This program is free software: you can redistribute it and/or modify
2.9 + * it under the terms of the GNU General Public License as published by
2.10 + * the Free Software Foundation, version 2 of the License.
2.11 + *
2.12 + * This program is distributed in the hope that it will be useful,
2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 + * GNU General Public License for more details.
2.16 + *
2.17 + * You should have received a copy of the GNU General Public License
2.18 + * along with this program. Look for COPYING file in the top folder.
2.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
2.20 + */
2.21 +package org.apidesign.bck2brwsr.tck;
2.22 +
2.23 +import java.util.Timer;
2.24 +import java.util.TimerTask;
2.25 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
2.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
2.27 +import org.testng.annotations.Factory;
2.28 +
2.29 +/**
2.30 + *
2.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
2.32 + */
2.33 +public class TimerTest {
2.34 + int miss;
2.35 + int exec;
2.36 +
2.37 + public TimerTest() {
2.38 + }
2.39 +
2.40 + @BrwsrTest public void scheduleTick() throws Exception {
2.41 + Timer t = new Timer("MyTest");
2.42 + class TT extends TimerTask {
2.43 + @Override
2.44 + public void run() {
2.45 + exec++;
2.46 + }
2.47 + }
2.48 + TT task = new TT();
2.49 + t.schedule(task, 15);
2.50 +
2.51 + if (exec == 0) {
2.52 + miss++;
2.53 + throw new InterruptedException();
2.54 + }
2.55 +
2.56 + assert exec == 1 : "One exec: " + exec;
2.57 + assert miss == 1 : "One miss: " + miss;
2.58 + }
2.59 +
2.60 + @BrwsrTest public void repeatedTicks() throws Exception {
2.61 + Timer t = new Timer("MyTest");
2.62 + class TT extends TimerTask {
2.63 + @Override
2.64 + public void run() {
2.65 + exec++;
2.66 + }
2.67 + }
2.68 + TT task = new TT();
2.69 + t.scheduleAtFixedRate(task, 15, 10);
2.70 +
2.71 + if (exec != 2) {
2.72 + miss++;
2.73 + throw new InterruptedException();
2.74 + }
2.75 +
2.76 + assert exec == 2 : "Two execs: " + exec;
2.77 + assert miss == 2 : "Two misses: " + miss;
2.78 + }
2.79 +
2.80 + @Factory public static Object[] create() {
2.81 + return VMTest.create(TimerTest.class);
2.82 + }
2.83 +
2.84 +}