/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
This subset of javax.realtime is provided for the JSR 302
Safety Critical Specification for Java
Copyright (C) 2008-2011, Martin Schoeberl (martin@jopdesign.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
@authors Martin Schoeberl, Lei Zhao, Ales Plsek, Tórur Strøm
*/
package javax.realtime;
import static javax.safetycritical.annotate.Level.LEVEL_2;
import javax.safetycritical.annotate.SCJAllowed;
import javax.safetycritical.annotate.SCJRestricted;
/**
* Class HighResolutionTime is the base class for AbsoluteTime, RelativeTime,
* RationalTime. Used to express time with nanosecond accuracy. This class is
* never used directly: it is abstract and has no public constructor. Instead,
* one of its subclasses AbsoluteTime, RelativeTime, or RationalTime should be
* used.
*
*/
@SCJAllowed
public abstract class HighResolutionTime { // implements Comparable {
static final int NANOS_PER_MILLI = 1000 * 1000;
/**
* milliseconds part of the time.
*/
long millis;
/**
* nanoseconds part of the time.
*/
int nanos;
/**
* the clock associated with this time.
* This is only interesting when user-defined clocks are
* used, which are a Level 2 feature.
*/
Clock clock;
HighResolutionTime(long millis, int nanos) {
clock = Clock.getRealtimeClock();
set(millis, nanos);
}
HighResolutionTime(HighResolutionTime time) {
millis = time.millis;
nanos = time.nanos;
clock = time.clock;
}
HighResolutionTime(long millis, int nanos, Clock clock) {
this.clock = clock;
set(millis, nanos);
}
/**
* Compares this HighResolutionTime with the specified HighResolutionTime
* time.
*
* @param time
* Compares with the time of this.
* @return
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public int compareTo(HighResolutionTime time) {
if (time == null)
throw new IllegalArgumentException("null parameter");
// We are missing reflection in JOP - T�rur 3/6/2011
/*if (getClass() != time.getClass())
throw new ClassCastException();*/
if (clock != time.clock)
throw new IllegalArgumentException("different clocks");
if (millis > time.millis)
return 1;
else if (millis < time.millis)
return -1;
else
return nanos - time.nanos;
}
/**
* Compares this HighResolutionTime with the specified object.
*
* @param object
* Compares with the time of this.
* @return
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public int compareTo(java.lang.Object object) {
return compareTo((HighResolutionTime) object);
}
/**
* Returns true if the argument object has the same type and values as this.
*
* @param time
* Value compared to this.
* @return true if the parameter object is of the same type and has the same
* values as this.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public boolean equals(HighResolutionTime time) {
return (millis == time.millis && nanos == time.nanos);
}
/**
* Returns true if the argument object has the same type and values as this.
*
* @param object
* Value compared to this.
* @return true if the parameter object is of the same type and has the same
* values as this.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public boolean equals(java.lang.Object object) {
return equals((HighResolutionTime)object);
}
/**
* At the moment just return the single real-time clock.
*
* @return A reference to the clock associated with this.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public Clock getClock() {
return clock;
}
/**
*
* @return The milliseconds component of the time represented by this.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public final long getMilliseconds() {
return millis;
}
/**
*
* @return The nanoseconds component of the time represented by this.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public final int getNanoseconds() {
return nanos;
}
/**
* Returns a hash code for this object in accordance with the general
* contract of Object.hashCode().
*
* @return The hashcode value for this instance.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public int hashCode() {
// TODO lookup the chapter how to best generate a hash code.
return (int) millis + nanos;
}
/**
* Sets the millisecond component of this to the given argument, and the
* nanosecond component of this to 0.
*
* @param millis
* This value shall be the value of the millisecond component of
* this at the completion of the call.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public void set(long millis) {
set(millis, 0);
}
/**
* Sets the millisecond and nanosecond components of this.
*
* @param millis
* The desired value for the millisecond component of this at the
* completion of the call. The actual value is the result of
* parameter normalization.
* @param nanos
* The desired value for the nanosecond component of this at the
* completion of the call. The actual value is the result of
* parameter normalization.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public void set(long millis, long nanos) {
final long millis_in_nanos = nanos / NANOS_PER_MILLI;
final int nanosleft = (int) (nanos % NANOS_PER_MILLI);
if (millis > 0) {
if (nanos < 0) { // no overflow possible
this.millis = millis + millis_in_nanos;
// ensure same sign
if (this.millis > 0 && nanosleft != 0) {
this.millis--;
this.nanos = nanosleft + NANOS_PER_MILLI;
} else {
this.nanos = nanosleft;
}
} else { // watch for overflow
long tmp = millis + millis_in_nanos;
if (tmp <= 0) {
// What should we do in case of overflow? - Tórur 3/6/2011
throw new ArithmeticException("overflow");
//return false
}
this.millis = tmp;
this.nanos = nanosleft;
}
} else if (millis < 0) {
if (nanos < 0) { // watch for negative overflow
long tmp = millis + millis_in_nanos;
if (tmp >= 0) {
// What should we do in case of overflow? - Tórur 3/6/2011
throw new ArithmeticException("overflow");
//return false
}
this.millis = tmp;
this.nanos = nanosleft;
} else { // no overflow possible
this.millis = millis + millis_in_nanos;
// ensure same sign
if (this.millis < 0 && nanosleft != 0) {
this.millis++;
this.nanos = nanosleft - NANOS_PER_MILLI;
} else {
this.nanos = nanosleft;
}
}
} else { // millis == 0
this.millis = millis_in_nanos;
this.nanos = nanosleft;
}
}
/**
* Change the value represented by this to that of the given time.
*
* @param time
* The new value for this.
*/
@SCJAllowed
@SCJRestricted(maySelfSuspend = false)
public void set(HighResolutionTime time) {
millis = time.millis;
nanos = time.nanos;
}
// /**
// * Behaves exactly like target.wait() but with the enhancement that it waits
// * with a precision of HighResolutionTime.
// *
// * @param target
// * The object on which to wait. The current thread must have a
// * lock on the object.
// * @param time
// * The time for which to wait. If it is RelativeTime(0,0) then
// * wait indefinitely. If it is null then wait indefinitely.
// * @throws java.lang.InterruptedException
// */
// @SCJAllowed(LEVEL_2)
// public static void waitForObject(java.lang.Object target,
// HighResolutionTime time) throws java.lang.InterruptedException {
// if (target == null)
// throw new NullPointerException("null target");
//
// if (time != null) {
// if (time.clock != Clock.single)
// throw new UnsupportedOperationException("Incompatible clock");
//
// if (time instanceof AbsoluteTime) {
// time = ((AbsoluteTime) time).subtract(Clock.single.getTime());
// //target.wait(time.getMilliseconds(), time.getNanoseconds());
// } else {
// /*if (time.isNegative())
// throw new IllegalArgumentException("negative relative time");
// else
// target.wait(time.getMilliseconds(), time.getNanoseconds());*/
// }
// } else
// target.wait();
// }
HighResolutionTime add(long millis, int nanos, HighResolutionTime dest) {
// if (!
dest.set(addSafe(this.millis, millis), ((long) this.nanos) + nanos);
// )
// throw new ArithmeticException("non-normalizable result");
// dest.setClock(_clock);
return dest;
}
/**
* Adds the two given values together, returning their sum if there is no
* overflow.
*/
static long addSafe(long arg1, long arg2) {
long sum = arg1 + arg2;
if ((arg1 > 0 && arg2 > 0 && sum <= 0)
|| (arg1 < 0 && arg2 < 0 && sum >= 0))
throw new ArithmeticException("overflow");
return sum;
}
}