1 /* 2 * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.glass.ui; 26 27 import java.lang.annotation.Native; 28 29 /** 30 * A high-resolution timer. 31 * 32 * An application may either override its run() method, or pass a Runnable 33 * object to the constructor of the Timer class. 34 * <p> 35 * The run() method may be invoked on a thread other than the UI thread. If 36 * a developer wants to process timer events on the UI thread, they can use 37 * the Application.invokeLater/invokeAndWait() API. 38 */ 39 public abstract class Timer { 40 41 @Native private final static double UNSET_PERIOD = -1.0; // 0 is valid value, so can't use it here 42 @Native private final static double SET_PERIOD = -2.0; // token value for vsync timer 43 44 private final Runnable runnable; 45 private long ptr; 46 private double period = UNSET_PERIOD; 47 48 protected abstract long _start(Runnable runnable); 49 protected abstract long _start(Runnable runnable, int period); 50 protected abstract void _stop(long timer); 51 52 /** 53 * Constructs a new timer. 54 * 55 * If the application overrides the Timer.run(), it should call super.run() 56 * in order to run the runnable passed to the constructor. 57 */ 58 protected Timer(Runnable runnable) { 59 if (runnable == null) { 60 throw new IllegalArgumentException("runnable shouldn't be null"); 61 } 62 this.runnable = runnable; 63 } 64 65 /** 66 * Returns the minimum timer period supported by the native system. 67 */ 68 public static int getMinPeriod() { 69 return Application.GetApplication().staticTimer_getMinPeriod(); 70 } 71 72 /** 73 * Returns the maximum timer period supported by the native system. 74 */ 75 public static int getMaxPeriod() { 76 return Application.GetApplication().staticTimer_getMaxPeriod(); 77 } 78 79 /** 80 * Starts the timer. 81 * The period must be in the range getMinPeriod() .. getMaxPeriod(). 82 * If the timer is currently started, it gets stopped before re-starting. 83 * If starting the timer fails, the RuntimeException is thrown. 84 */ 85 public synchronized void start(int period) { 86 if (period < getMinPeriod() || period > getMaxPeriod()) { 87 throw new IllegalArgumentException("period is out of range"); 88 } 89 90 if (this.ptr != 0L) { 91 stop(); 92 } 93 94 this.ptr = _start(this.runnable, period); 95 if (this.ptr == 0L) { 96 this.period = UNSET_PERIOD; 97 throw new RuntimeException("Failed to start the timer"); 98 } else { 99 this.period = (double)period; 100 } 101 } 102 103 /** 104 * Start a vsync-based timer if the system supports it. 105 * 106 * A RuntimeException is thrown if the system does not support 107 * vsync-based timer or if there was an issue starting the timer. 108 */ 109 public synchronized void start() { 110 if (this.ptr != 0L) { 111 stop(); 112 } 113 114 this.ptr = _start(this.runnable); 115 if (this.ptr == 0L) { 116 this.period = UNSET_PERIOD; 117 throw new RuntimeException("Failed to start the timer"); 118 } else { 119 this.period = SET_PERIOD; 120 } 121 } 122 123 /** 124 * Stops the timer. If a vsync-based timer is stopped, all of the 125 * vsync timers currently running will be stopped. 126 */ 127 public synchronized void stop() { 128 if (this.ptr != 0L) { 129 _stop(this.ptr); 130 this.ptr = 0L; 131 this.period = UNSET_PERIOD; 132 } 133 } 134 135 /** 136 * Returns true if the timer is currently running 137 * (convenience API: might not need it) 138 */ 139 public synchronized boolean isRunning() { 140 return (this.period != UNSET_PERIOD); 141 } 142 }