001    package javax.realtime;
002    
003    /** A <code>Timer</code> is a timed event that measures time
004     *  relative to a given <code>Clock</code>. This class defines
005     *  basic functionality available to all timers. Applications
006     *  will generally use either <code>PeriodicTimer</code> to
007     *  create an event that is fired repeatedly at regular intervals,
008     *  of <code>OneShotTimer</code>, which provides the basic
009     *  facilities of something that ticks along following some
010     *  time line (real-time, cpu-time, user-time, simulation-time,
011     *  etc.). All timers are created disabled and do nothing
012     *  until <code>start()</code> is called.
013     */
014    public abstract class Timer extends AsyncEvent {
015    
016        protected boolean enabled = true;
017        protected boolean started = false;
018        protected Clock defaultClock;
019        protected RelativeTime fireAfter;
020        protected AsyncEventHandler handler;
021        protected RelativeTime timePassed = new RelativeTime(0, 0);
022        protected AbsoluteTime lastUpdated = new AbsoluteTime();
023    
024        /** Create a timer that fires at the given time based on the given
025         *  instance of <code>Clock</code> and is handled by the specified
026         *  handler.
027         *
028         *  @param t The time to fire the event. Will be converted to
029         *           absolute time.
030         *  @param clock The clock on which to base this time. If null, the
031         *               system realtime clock is used.
032         *  @param handler The default handler to use for this event. If null, no
033         *                 handler is associated with it and nothing will happen
034         *                 when this event fires until a handler is provided.
035         */
036        protected Timer(HighResolutionTime t, Clock c,
037                        AsyncEventHandler handler) {
038            if (t instanceof AbsoluteTime)
039                fireAfter = new RelativeTime(((RelativeTime)t).getMilliseconds() -
040                                             c.getTime().getMilliseconds(),
041                                             ((RelativeTime)t).getNanoseconds() -
042                                             c.getTime().getNanoseconds());
043            else fireAfter = (RelativeTime)t;
044    
045            defaultClock = c;
046            this.handler = handler;
047            enabled = false;
048        }
049    
050        /** Create a <code>ReleaseParameters</code> block appropriate to the
051         *  timing characteristics of this event. The default is the most
052         *  pessimistic: <code>AperiodicParameters</code>. This is typically
053         *  called by code that is setting up a handler for this event that
054         *  will fill in the parts of the release parameters for which it has
055         *  values, e.g, cost.
056         *
057         *  @return A new <code>ReleaseParameters</code> object.
058         */
059        public ReleaseParameters createReleaseParameters() {
060            return new AperiodicParameters(null, fireAfter, handler, null);
061        }
062    
063        /** Destroy the timer and return all possible resources to the system. */
064        public void destroy() {
065            defaultClock = null;
066            fireAfter = null;
067            handler = null;
068            enabled = false;
069        }
070    
071        /** Disable this timer, preventing it from firing. It may subsequently
072         *  be re-enabled. If the timer is disabled when its fire time occurs
073         *  then it will not fire. However, a disabled timer continues to
074         *  count while it is disabled and if it is subsequently reabled
075         *  before its fire time occures and is enabled when its fire time
076         *  occurs, it will fire.
077         */
078        public void disable() {
079            enabled = false;
080        }
081    
082        /** Re-enable this timer after it has been disabled. */
083        public void enable() {
084            enabled = true;
085        }
086    
087        /** Gets the instance of <code>Clock</code> that this timer is based on.
088         *
089         *  @return The instance of <code>Clock</code>.
090         */
091        public Clock getClock() {
092            return defaultClock;
093        }
094    
095        /** Get the time at which this event will fire.
096         *
097         *  @return An instance of <code>AbsoluteTime</code> object representing
098         *          the absolute time at which this will fire.
099         */
100        public AbsoluteTime getFireTime() {
101            return new AbsoluteTime(fireAfter.getMilliseconds() -
102                                    defaultClock.getTime().getMilliseconds() +
103                                    Clock.getRealtimeClock().getTime().getMilliseconds(),
104                                    fireAfter.getNanoseconds() -
105                                    defaultClock.getTime().getNanoseconds() +
106                                    Clock.getRealtimeClock().getTime().getNanoseconds());
107        }
108    
109        /** Tests this to determine if this has been started and is in a
110         *  state (enabled) such that when the given time occurs it will
111         *  fire the event.
112         *
113         *  @return True if the timer has been started and is in the enabled
114         *          state. False, if the timer has either not been started,
115         *          started and is in the disabled state, or started and stopped.
116         */
117        public boolean isRunning() {
118            return (started && enabled);
119        }
120    
121        /** Change the schedule time for this event; can take either absolute
122         *  or relative times.
123         *
124         *  @param time The time to reschedule for this event firing. If null, the
125         *              previous fire time is still the time at which this will fire.
126         */
127        public void reschedule(HighResolutionTime time) {
128            if (time instanceof AbsoluteTime)
129                fireAfter.set(time.getMilliseconds() - defaultClock.getTime().getMilliseconds(),
130                              time.getNanoseconds() - defaultClock.getTime().getNanoseconds());
131            else fireAfter = (RelativeTime)time;
132        }
133    
134        /** Starts this time. A <code>Timer</code> starts measuring time from
135         *  when it is started.
136         */
137        public void start() {
138            started = true;
139            Clock.getRealtimeClock().getTime(lastUpdated);
140            while (started) {
141                AbsoluteTime temp = new AbsoluteTime();
142                Clock.getRealtimeClock().getTime(temp);
143                RelativeTime difference = temp.subtract(lastUpdated);
144                timePassed = timePassed.add(difference);
145                lastUpdated = temp;
146            }
147        }
148    
149        /** Stops a timer that is running and changes its state to
150         *  <i>not started</i>.
151         *
152         *  @return True, if this was <b>started and enabled</b> and stops this.
153         *          False, if this was not <b>started or disabled</b>.
154         */
155        public boolean stop() {
156            boolean wasStarted = started && enabled;
157            started = false;
158            return wasStarted;
159        }
160    }