001    package javax.realtime;
002    
003    /** An object that represents a time interval millis/1E3+nanos/1E9
004     *  seconds long that is divided into subintervals by some frequency.
005     *  This is generally used in periodic events, threads, and
006     *  feasibility analysis to specify periods where there is a basic
007     *  period that must be adhered to strictly (the interval), but
008     *  within that interval the periodic events are supposed to happen
009     *  <code>frequency</code> times, as u niformly spaced as possible,
010     *  but clock and scheduling jitter is moderately acceptable.
011     *  <p>
012     *  If the value of any of the millisecond or nanosecond fields is
013     *  negative the variable is set to negative value. Although logically
014     *  this may represent time before the epoch, invalid results may
015     *  occur if an instance of <code>AbsoluteTime</code> representing
016     *  time before the epoch is given as a parameter to a method.
017     *  <p>
018     *  <b>Caution:</b> This class is explicitly unsafe in multithreaded
019     *  situations when it is being changed. No synchronization is done. It
020     *  is assumed that users of this class who are mutating instances will
021     *  be doing their own synchronization at a higher level.
022     */
023    public class RationalTime extends RelativeTime {
024    
025        private int frequency;
026    
027        /** Constructs an instance of <code>RationalTime</code>. Equivalent to
028         *  <code>new RationalTime(frequency, 1000, 0)</code> -- essentially a
029         *  cycle-per-seconds value.
030         *
031         *  @param frequency The frequency value.
032         */
033        public RationalTime(int frequency) {
034            // I think they messed up the order of the parameters in the spec.
035            this(frequency, 1000, 0);
036        }
037    
038        /** Constructs an instance of <code>RationalTime</code>. All arguments
039         *  must be greater than or equal to zero.
040         *
041         *  @param frequency The frequency value.
042         *  @param millis The milliseconds value.
043         *  @param nanos The nanoseconds value.
044         *  @throws java.lang.IllegalArgumentException If any of the argument values
045         *                                             are less than zero.
046         */
047        public RationalTime(int frequency, long millis, int nanos)
048            throws IllegalArgumentException {
049            super(millis, nanos);
050            this.frequency = frequency;
051        }
052    
053        /** Constructs an instance of <code>RationalTime</code> from the given
054         *  <code>RelativeTime</code>.
055         *
056         *  @param frequency The frequency value.
057         *  @param interval The given instance of <code>RelativeTime</code>.
058         *  @throws java.lang.IllegalArgumentException If any of the argument values
059         *                                             are less than zero.
060         */
061        public RationalTime(int frequency, RelativeTime interval)
062            throws IllegalArgumentException {
063            this(frequency, interval.getMilliseconds(),
064                 interval.getNanoseconds());
065        }
066    
067        /** Convert this time to an absolute time.
068         *
069         *  @param clock The reference clock. If null, <code>Clock.getRealTimeClock()</code>
070         *               is used.
071         *  @param destination A reference to the destination istance.
072         */
073        public AbsoluteTime absolute(Clock clock, AbsoluteTime destination) {
074            if (destination == null)
075                destination = new AbsoluteTime();
076            if (clock == null)
077                clock = Clock.getRealtimeClock();
078            
079            destination.set(clock.getTime().add(this));
080            return destination;
081        }
082    
083        /** Add this time to an <code>AbsoluteTime</code>. It is almost the same as
084         *  <code>destination.add(this, destination)</code> except that it accounts
085         *  for (ie. divides by) the frequency.
086         */
087        public void addInterarrivalTo(AbsoluteTime destination) {
088            destination.add(this, destination);
089        }
090    
091        /** Gets the value of <code>frequency</code>.
092         *
093         *  @return The value of <code>frequency</code> as an integer.
094         */
095        public int getFrequency() {
096            return frequency;
097        }
098    
099        /** Gets the interarrival time. This time is
100         *  <code>(milliseconds/10^3 + nanoseconds/10^9)/frequency<code> rounded
101         *  down to the nearest expressible value of the fields and their types 
102         *  of <code>RelativeTime</code>.
103         */
104        public RelativeTime getInterarrivalTime() {
105            RelativeTime temp = new RelativeTime();
106            long t =  Math.round((1000000 * getMilliseconds() + getNanoseconds()) /
107                                 getFrequency());
108            temp.set(t / 1000000, (int) (t % 1000000));
109            return temp;
110        }
111    
112        /** Gets the interarrival time. This time is
113         *  <code>(milliseconds/10^3 + nanoseconds/10^9)/frequency<code> rounded
114         *  down to the nearest expressible value of the fields and their types 
115         *  of <code>RelativeTime</code>.
116         *
117         *  @param dest Result is stored in <code>dest</code> and returned; if null,
118         *              a new object is returned.
119         */
120        public RelativeTime getInterarrivalTime(RelativeTime dest) {
121            if (dest == null) dest = new RelativeTime();
122            long t =  Math.round((1000000 * getMilliseconds() + getNanoseconds()) /
123                                 getFrequency());
124            dest.set(t / 1000000, (int) (t % 1000000));
125            return dest;
126        }
127    
128        /** Sets the indicated fields to the given values.
129         *
130         *  @param millis The new value for the millisecond field.
131         *  @param nanos The new value for the nanosecond field.
132         *  @throws java.lang.IllegalArgumentException
133         */
134        public void set(long millis, int nanos)
135            throws IllegalArgumentException {
136            super.set(millis, nanos);
137        }
138    
139        /** Sets the value of the <code>frequency</code> field.
140         *
141         *  @param frequency The new value for the <code>frequency</code>.
142         *  @throws java.lang.ArithmeticException
143         */
144        public void setFrequency(int frequency) throws ArithmeticException {
145            this.frequency = frequency;
146        }
147    }