1 /******************************************************************************* 2 * Copyright (c) 2000, 2011 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.internal.debug.core.model; 15 16 /** 17 * A timer notifies listeners when a specific amount of time has passed. 18 * 19 * @see ITimeoutListener 20 */ 21 public class Timer { 22 23 /** 24 * Listener to notify of a timeout 25 */ 26 private ITimeoutListener fListener; 27 28 /** 29 * Timeout value, in milliseconds 30 */ 31 private int fTimeout; 32 33 /** 34 * Whether this timer's thread is alive 35 */ 36 private boolean fAlive = true; 37 38 /** 39 * Whether this timer has been started and has not yet timed out or been 40 * stopped. 41 */ 42 private boolean fStarted = false; 43 44 /** 45 * The single thread used for each request. 46 */ 47 private Thread fThread; 48 49 /** 50 * Constructs a new timer 51 */ Timer()52 public Timer() { 53 setTimeout(Integer.MAX_VALUE); 54 Runnable r = new Runnable() { 55 @Override 56 public void run() { 57 while (isAlive()) { 58 boolean interrupted = false; 59 try { 60 Thread.sleep(getTimeout()); 61 } catch (InterruptedException e) { 62 interrupted = true; 63 } 64 if (!interrupted) { 65 if (getListener() != null) { 66 setStarted(false); 67 setTimeout(Integer.MAX_VALUE); 68 getListener().timeout(); 69 setListener(null); 70 } 71 } 72 } 73 } 74 }; 75 setThread(new Thread(r, "Evaluation Timer")); //$NON-NLS-1$ 76 getThread().setDaemon(true); 77 getThread().start(); 78 } 79 80 /** 81 * Starts this timer, and notifies the given listener when the time has 82 * passed. A call to <code>stop</code>, before the time expires, will cancel 83 * the the timer and timeout callback. This method can only be called if 84 * this timer is idle (i.e. <code>isStarted() == false<code>). 85 * 86 * @param listener 87 * The timer listener 88 * @param ms 89 * The number of milliseconds to wait before notifying the 90 * listener 91 */ start(ITimeoutListener listener, int ms)92 public void start(ITimeoutListener listener, int ms) { 93 if (isStarted()) { 94 throw new IllegalStateException( 95 JDIDebugModelMessages.Timer_Timer_cannot_be_started_more_than_once_1); 96 } 97 setListener(listener); 98 setTimeout(ms); 99 setStarted(true); 100 getThread().interrupt(); 101 } 102 103 /** 104 * Stops this timer, cancelling any pending timeout notification. 105 */ stop()106 public void stop() { 107 if (isAlive()) { 108 setStarted(false); 109 setTimeout(Integer.MAX_VALUE); 110 getThread().interrupt(); 111 } 112 } 113 114 /** 115 * Disposes this timer 116 */ dispose()117 public void dispose() { 118 if (isAlive()) { 119 setAlive(false); 120 getThread().interrupt(); 121 setThread(null); 122 } 123 } 124 125 /** 126 * Returns whether this timer's thread is alive 127 * 128 * @return whether this timer's thread is alive 129 */ isAlive()130 private boolean isAlive() { 131 return fAlive; 132 } 133 134 /** 135 * Sets whether this timer's thread is alive. When set to <code>false</code> 136 * this timer's thread will exit on its next iteration. 137 * 138 * @param alive 139 * whether this timer's thread should be alive 140 * @see #dispose() 141 */ setAlive(boolean alive)142 private void setAlive(boolean alive) { 143 fAlive = alive; 144 } 145 146 /** 147 * Returns the current timeout listener 148 * 149 * @return timeout listener 150 */ getListener()151 protected ITimeoutListener getListener() { 152 return fListener; 153 } 154 155 /** 156 * Sets the listener to be notified if this timer times out. 157 * 158 * @param listener 159 * timeout listener 160 */ setListener(ITimeoutListener listener)161 private void setListener(ITimeoutListener listener) { 162 fListener = listener; 163 } 164 165 /** 166 * Returns whether this timer has been started, and has not yet timed out, 167 * or been stopped. 168 * 169 * @return whether this timer has been started, and has not yet timed out, 170 * or been stopped 171 */ isStarted()172 public boolean isStarted() { 173 return fStarted; 174 } 175 176 /** 177 * Sets whether this timer has been started, and has not yet timed out, or 178 * been stopped. 179 * 180 * @param started 181 * whether this timer has been started, and has not yet timed 182 * out, or been stopped 183 */ setStarted(boolean started)184 private void setStarted(boolean started) { 185 fStarted = started; 186 } 187 188 /** 189 * Returns this timer's thread 190 * 191 * @return thread that waits for a timeout 192 */ getThread()193 private Thread getThread() { 194 return fThread; 195 } 196 197 /** 198 * Sets this timer's thread used to perform timeout processing 199 * 200 * @param thread 201 * thread that waits for a timeout 202 */ setThread(Thread thread)203 private void setThread(Thread thread) { 204 fThread = thread; 205 } 206 207 /** 208 * Returns the amount of time, in milliseconds, that this timer is/was 209 * waiting for. 210 * 211 * @return timeout value, in milliseconds 212 */ getTimeout()213 protected int getTimeout() { 214 return fTimeout; 215 } 216 217 /** 218 * Sets the amount of time, in milliseconds, that this timer will wait for 219 * before timing out. 220 * 221 * @param timeout 222 * value, in milliseconds 223 */ setTimeout(int timeout)224 private void setTimeout(int timeout) { 225 fTimeout = timeout; 226 } 227 } 228