/**************************************************************************
* File name : HighResolutionTime.java
*
* This file is part a SCJ Level 0 and Level 1 implementation,
* based on SCJ Draft, Version 0.94 25 June 2013.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This SCJ Level 0 and Level 1 implementation 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this SCJ Level 0 and Level 1 implementation.
* If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012
* @authors Anders P. Ravn, Aalborg University, DK
* Stephan E. Korsholm and Hans Søndergaard,
* VIA University College, DK
*************************************************************************/
package javax.realtime;
import icecaptools.IcecapCompileMe;
import javax.safetycritical.annotate.SCJAllowed;
/**
* <code>HighResolutionTime</code> is the base class for time given with nanosecond accuracy.<p>
* A time object in normalized form represents negative time if both components are
* nonzero and negative, or one is nonzero and negative and the other is zero. <br>
* For add and subtract operations, negative values behave as they do in Java arithmetic.
* <p>
* Methods of this class are not synchronized by the implementation.
*
* @version 1.2; - December 2013
*
* @author Anders P. Ravn, Aalborg University,
* <A HREF="mailto:apr@cs.aau.dk">apr@cs.aau.dk</A>, <br>
* Hans Søndergaard, VIA University College, Denmark,
* <A HREF="mailto:hso@viauc.dk">hso@via.dk</A>
*
* @scjComment
* - semantic issue: clock is only meaningful for <code>AbsoluteTime</code> <br>
* - semantic issue: Java arithmetic means no overflow detection <br>
* - semantic issue: method <code>set</code>: if parameter null, no Exception? <p>
*
* - implementation issue:
* <code>public int compareTo (Object arg0)</code> is inherited from
* <code>interface Comparable</code> <br>
*/
@SCJAllowed
public abstract class HighResolutionTime implements
Comparable<HighResolutionTime> {
Clock clock;
long millis;
int nanos;
HighResolutionTime(long millis, int nanos, Clock clock) {
if (!isNormalized(millis, nanos)) {
setNormalized(millis, nanos);
}
else {
this.millis = millis;
this.nanos = nanos;
}
this.clock = clock;
}
private boolean isNormalized(long millis, int nanos) {
return (millis >= 0L && (0 <= nanos && nanos < 1000000))
|| (millis <= 0L && (-1000000 < nanos && nanos <= 0));
}
/**
*
* @return a reference to the clock associated with <code>this</code>.
*/
public final Clock getClock() {
return this.clock;
}
/**
*
* @return the milliseconds component of the time represented by <code>this</code>.
*/
public final long getMilliseconds() {
return this.millis;
}
/**
*
* @return the nanoseconds component of the time represented by <code>this</code>.
*/
public final int getNanoseconds() {
return this.nanos;
}
/**
* Change the value represented by <code>this</code> to that of the given <code>time</code>.
*
* @param time is the new value for <code>this</code>.
*
* @throws ClassCastException if the <code>time</code> parameter is not
* of the same class as <code>this</code>.
* @throws IllegalArgumentException if the <code>time</code> parameter is
* not associated with the same clock as <code>this</code>, or when
* the <code>time</code> parameter is null.
*/
public void set(HighResolutionTime time) {
if (time == null)
throw new IllegalArgumentException("null parameter");
if (this.getClass() != time.getClass())
throw new ClassCastException("from HighResolutionTime :: set");
this.millis = time.millis;
this.nanos = time.nanos;
this.clock = time.clock;
}
/**
* Sets the millisecond component of <code>this</code> to the given argument,
* and the nanosecond component of <code>this</code> to 0.
* The clock is unchanged.
*
* @param millis is the new value of the millisecond component.
*/
public void set(long millis) {
this.millis = millis;
this.nanos = 0;
}
/**
* Sets the millisecond and nanosecond components of <code>this</code> to the given arguments.
* The clock is unchanged.
*
* @param millis is the new value of the millisecond component.
* @param nanos is the new value of the nanosecond component.
*/
public void set(long millis, int nanos) {
if (!isNormalized(millis, nanos))
setNormalized(millis, nanos);
else {
this.millis = millis;
this.nanos = nanos;
}
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (millis ^ (millis >>> 32));
result = prime * result + nanos;
return result;
}
/**
* @param time
* @return true just when the parameter <code>time</code> is of the same
* type and has the same values as <code>this</code>.
*/
public boolean equals(HighResolutionTime time) {
if (time == null)
return false;
return (this.getClass() == time.getClass())
&& (this.millis == time.getMilliseconds())
&& (this.nanos == time.getNanoseconds())
&& (this.clock == time.getClock());
}
public boolean equals(Object object) {
HighResolutionTime time = null;
if (object instanceof HighResolutionTime)
time = (HighResolutionTime) object;
if (object instanceof AbsoluteTime)
time = (AbsoluteTime) object;
if (object instanceof RelativeTime)
time = (RelativeTime) object;
else
time = null;
if (time == null || object == null)
return false;
return (this.getClass() == time.getClass())
&& (this.millis == time.getMilliseconds())
&& (this.nanos == time.getNanoseconds())
&& (this.clock == time.getClock());
}
/**
* Compares <code>this</code> with the specified <code>HighResolutionTime time</code>.
*
* @param time is the second argument to the comparison.
*
* @return a negative integer, zero, or a positive integer as <code>this</code>
* object is less than, equal to, or greater than <code>time</code>.
*
* @throws ClassCastException if the <code>time</code> parameter is not
* of the same class as <code>this</code>.
* @throws IllegalArgumentException if the <code>time</code> parameter is
* not associated with the same clock as <code>this</code>, or when
* the <code>time</code> parameter is null.
*/
public int compareTo(HighResolutionTime time) {
if (time == null)
throw new IllegalArgumentException();
if (this.getClass() != time.getClass())
throw new ClassCastException();
if (this.clock != time.getClock())
throw new IllegalArgumentException();
if (this.millis < time.getMilliseconds())
return -1;
else if (this.millis > time.getMilliseconds())
return 1;
else if (this.nanos < time.getNanoseconds())
return -1;
else if (this.nanos > time.getNanoseconds())
return 1;
else
return 0;
}
public String toString() {
return ("(ms,ns) = (" + millis + ", " + nanos + ")");
}
static final int NANOS_PER_MILLI = 1000000;
/**
* Sets the normalized values of millis and nanos in this.
*/
@IcecapCompileMe // Don't remove this CompileMe annotation
final void setNormalized(final long ms, final int ns) {
/*
* Examples:
* 3.12 millis = 3 millis and 120*1000 nanos
* 0.12 millis = 0 millis and 120*1000 nanos
* 0.00 millis = 0 millis and 0*1000 nanos
* -3.12 millis = -3 millis and -120*1000 nanos
* -0.12 millis = 0 millis and -120*1000 nanos
* -0.00 millis = -0 millis and - 0*1000 nanos
*/
// nanos == nanos/NANOS_PER_MILLI + nanos%NANOS_PER_MILLI
millis = ms + ns / NANOS_PER_MILLI;
nanos = ns % NANOS_PER_MILLI;
if (millis > 0 && nanos < 0) {
millis--; // millis >= 0
nanos += NANOS_PER_MILLI;
} else if (millis < 0 && nanos > 0) {
millis++; // millis <= 0
nanos -= NANOS_PER_MILLI;
}
}
// public static boolean waitForObject(Object target, HighResolutionTime time) {
// return javax.safetycritical.PriorityScheduler.waitForObject(target, time);
// }
// used for JML annotation only (not public)
long getMillis() {
return millis;
}
// used for JML annotation only (not public)
int getNanos() {
return nanos;
}
}