/************************************************************************** * 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; } }