001    // RelativeTime.java, created by cata
002    // Copyright (C) 2001 Catalin Francu <cata@mit.edu>
003    //    taking over Bryan Fink's code
004    // Licensed under the terms of the GNU GPL; see COPYING for details.
005    
006    // Class Invariant:
007    //   - Times are consistent at any time. That is, 0<=nanos<1000000. If not,
008    //     we normalize them, e.g 3ms 3200000ns --> 6ms 200000ns
009    
010    package javax.realtime;
011    import java.lang.Math;
012    
013    /** Class <code>HighResolutiontime</code> is the base class for
014     *  <code>AbsoluteTime, RelativeTime, RationalTime</code>.
015     */
016    public abstract class HighResolutionTime implements Comparable {
017        
018        private long millis;
019        private int nanos;
020        static protected Clock defaultClock = Clock.getRealtimeClock();
021        
022        /** Convert the time of <code>this</code> to an absolute time, relative to
023         *  the given instance of <code>Clock</code>. Convenient for situations
024         *  where you really need an absolute time. Aloocates a destination object
025         *  if necessary.
026         *
027         *  @param clock An instance of <code>Clock</code> is used to convert the
028         *               time of <code>this</code> into absolute time.
029         */
030        public abstract AbsoluteTime absolute(Clock clock);
031    
032        /** Convert the time of <code>this</code> to an absolute time, relative to
033         *  the given instance of <code>Clock</code>. Convenient for situations
034         *  where you really need an absolute time. Aloocates a destination object
035         *  if necessary.
036         *
037         *  @param clock An instance of <code>Clock</code> is used to convert the
038         *               time of <code>this</code> into absolute time.
039         *  @param dest If null, a new object is created and returned as result,
040         *              else <code>dest</code> is returned.
041         */
042        public abstract AbsoluteTime absolute(Clock c, AbsoluteTime dest);
043        
044        /** Compares this <code>HighResolutionTime</code> with the specified
045         *  <code>HighResolutionTime</code>.
046         *
047         *  @param time Compares with the time of <code>this</code>.
048         */
049        public int compareTo(HighResolutionTime b) {
050            if (millis > b.getMilliseconds())
051                return 1;
052            
053            if (millis < b.getMilliseconds())
054                return -1;
055            
056            if (nanos > b.getNanoseconds())
057                return 1;
058            
059            if (nanos < b.getNanoseconds())
060                return -1;
061            
062            return 0;
063        }
064        
065        /** Compares this <code>HighResolutionTime</code> with the specified
066         *  <code>HighResolutionTime</code>.
067         */
068        public int compareTo(Object b) {
069            return compareTo((HighResolutionTime) b);
070        }
071        
072        /** Returns true if the argument object has the same values as this. */
073        public boolean equals(HighResolutionTime b) {
074            return (millis == b.getMilliseconds() &&
075                    nanos == b.getNanoseconds());
076        }
077        
078        /** Returns true if the argument object has the same values as <code>this<code>.
079         *
080         *  @param b Value compared to <code>this</code>.
081         */
082        public boolean equals(Object b) {
083            return equals((HighResolutionTime) b);
084        }
085        
086        /** Returns the milliseconds component of <code>this</code>.
087         *
088         *  @return The milliseconds component of the time past the epoch
089         *          represented by <code>this</code>.
090         */
091        public final long getMilliseconds() {
092            return millis;
093        }
094        
095        /** Returns the nanoseconds component of <code>this</code>. */
096        public final int getNanoseconds()   {
097            return nanos;
098        }
099        
100        public int hashCode()       {
101            return (int)(nanos+millis*1000000);
102        }
103    
104        /** Convert the time of <code>this</code> to a relative time, with
105         *  respect to the given instance of <code>Clock</code>. Convenient
106         *  for situations where you really need a relative time. Allocates
107         *  a destination object if necessary.
108         *
109         *  @param clock An instance of <code>Clock</code> is used to convert
110         *               the time of <code>this</code> into realtive time.
111         */
112        public abstract RelativeTime relative(Clock clock);
113    
114        /** Convert the time of <code>this</code> to a relative time, with
115         *  respect to the given instance of <code>Clock</code>. Convenient
116         *  for situations where you really need a relative time. Allocates
117         *  a destination object if necessary.
118         *
119         *  @param clock An instance of <code>Clock</code> is used to convert
120         *               the time of <code>this</code> into realtive time.
121         *  @param time If null, a new object is created and returned as result,
122         *              else <code>time</code> is returned.
123         */
124        public abstract RelativeTime relative(Clock clock,
125                                              HighResolutionTime time);
126    
127        /** Change the value represented by <code>this</code> to that of the given
128         *  time. If the type of <code>this</code> and the type of the given time
129         *  are not the same this method will throw IllegalArgumentException.
130         *
131         *  @param t The new value for <code>this</code>.
132         */
133        public void set(HighResolutionTime t) {
134            millis = t.getMilliseconds();
135            nanos = t.getNanoseconds();
136        }
137    
138        /** Sets the millisecond component of <code>this</code> to the given argument.
139         *
140         *  @param millis This value will be the value of the milliseconds component
141         *                of <code>this</code> at the completion of the call. If
142         *                <code>millis</code> is negative the millisecond value of
143         *                <code>this</code> is set to negative value. Although
144         *                logically this may represent time before the epoch, invalid
145         *                results may occur if a <code>HighResolutionTime</code>
146         *                representing time before the epoch is given as a parameter
147         *                to the method.
148         */
149        public void set(long millisecs) {
150            millis = millisecs;
151            nanos = 0;
152        }
153        
154        /** Sets the millisecond and nanosecond compenonets of <code>this</code>.
155         *
156         *  @param millis Value to set millisecond part of <code>this</code>. If
157         *                <code>millis</code> is negative the millisecond value
158         *                of <code>this</code> is set to negative value. Although
159         *                logically this may represent time before the epoch,
160         *                invalid results may occur if a <code>HighResolutionTime</code>
161         *                representing time before the epoch is given as a parameter
162         *                to the method.
163         *  @param nanos Value to set nanosecond part of <code>this</code>. If
164         *               <code>nanos</code> is negative, the nanosecond valur of
165         *               <code>this</code> is set to negative value. Although
166         *               logically this may represent time before the epoch, invalid
167         *               results may occur if a <code>HighResolutionTime</code>
168         *               representing time before the epoch is given as a paramter
169         *               to the method.
170         */
171        public void set(long millisecs, int nanosecs) {
172            // Do we have negative nanos? Java cannot take negative moduli properly
173            if (nanosecs < 0) {
174                nanos = Math.abs(nanosecs);
175                millis = millisecs - nanos/1000000;
176                nanos %= 1000000;
177                if (nanos > 0) {
178                    millis--;
179                    nanos = 1000000 - nanos;
180                }
181            }
182            else {
183                millis = millisecs + nanosecs/1000000;
184                nanos = nanosecs%1000000;
185            }
186        }
187    
188        /** Behaves exactly like <code>target.wait()</code> but with the enhacement
189         *  that it waits with a precision of <code>HighResolutionTime</code>.
190         *
191         *  @param target The object on which to wait. The current thread must have
192         *                a lock on the object.
193         *  @param time The time for which to wait. If this is
194         *              <code>RelativeTime(0, 0)</code> then wait indefinetly.
195         *  @throws java.lang.InterruptedException If another thread interrupts this
196         *                                         thread while it is waiting.
197         */
198        public static void waitForObject(Object target, HighResolutionTime time)
199            throws InterruptedException {
200            target.wait(time.getMilliseconds(), time.getNanoseconds());
201        }
202    
203        /** Returns <code>millis * 1000000 + nanos</code>. */
204        public long time() {
205            return (millis * 1000000 + nanos);
206        }
207    }