1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/licenses/publicdomain
  34  */
  35 
  36 package java.util.concurrent;
  37 
  38 /**
  39  * A <tt>TimeUnit</tt> represents time durations at a given unit of
  40  * granularity and provides utility methods to convert across units,
  41  * and to perform timing and delay operations in these units.  A
  42  * <tt>TimeUnit</tt> does not maintain time information, but only
  43  * helps organize and use time representations that may be maintained
  44  * separately across various contexts.  A nanosecond is defined as one
  45  * thousandth of a microsecond, a microsecond as one thousandth of a
  46  * millisecond, a millisecond as one thousandth of a second, a minute
  47  * as sixty seconds, an hour as sixty minutes, and a day as twenty four
  48  * hours.
  49  *
  50  * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
  51  * how a given timing parameter should be interpreted. For example,
  52  * the following code will timeout in 50 milliseconds if the {@link
  53  * java.util.concurrent.locks.Lock lock} is not available:
  54  *
  55  * <pre>  Lock lock = ...;
  56  *  if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
  57  * </pre>
  58  * while this code will timeout in 50 seconds:
  59  * <pre>
  60  *  Lock lock = ...;
  61  *  if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
  62  * </pre>
  63  *
  64  * Note however, that there is no guarantee that a particular timeout
  65  * implementation will be able to notice the passage of time at the
  66  * same granularity as the given <tt>TimeUnit</tt>.
  67  *
  68  * @since 1.5
  69  * @author Doug Lea
  70  */
  71 public enum TimeUnit {
  72     NANOSECONDS {
  73         public long toNanos(long d)   { return d; }
  74         public long toMicros(long d)  { return d/(C1/C0); }
  75         public long toMillis(long d)  { return d/(C2/C0); }
  76         public long toSeconds(long d) { return d/(C3/C0); }
  77         public long toMinutes(long d) { return d/(C4/C0); }
  78         public long toHours(long d)   { return d/(C5/C0); }
  79         public long toDays(long d)    { return d/(C6/C0); }
  80         public long convert(long d, TimeUnit u) { return u.toNanos(d); }
  81         int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
  82     },
  83     MICROSECONDS {
  84         public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
  85         public long toMicros(long d)  { return d; }
  86         public long toMillis(long d)  { return d/(C2/C1); }
  87         public long toSeconds(long d) { return d/(C3/C1); }
  88         public long toMinutes(long d) { return d/(C4/C1); }
  89         public long toHours(long d)   { return d/(C5/C1); }
  90         public long toDays(long d)    { return d/(C6/C1); }
  91         public long convert(long d, TimeUnit u) { return u.toMicros(d); }
  92         int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
  93     },
  94     MILLISECONDS {
  95         public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
  96         public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
  97         public long toMillis(long d)  { return d; }
  98         public long toSeconds(long d) { return d/(C3/C2); }
  99         public long toMinutes(long d) { return d/(C4/C2); }
 100         public long toHours(long d)   { return d/(C5/C2); }
 101         public long toDays(long d)    { return d/(C6/C2); }
 102         public long convert(long d, TimeUnit u) { return u.toMillis(d); }
 103         int excessNanos(long d, long m) { return 0; }
 104     },
 105     SECONDS {
 106         public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
 107         public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
 108         public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
 109         public long toSeconds(long d) { return d; }
 110         public long toMinutes(long d) { return d/(C4/C3); }
 111         public long toHours(long d)   { return d/(C5/C3); }
 112         public long toDays(long d)    { return d/(C6/C3); }
 113         public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
 114         int excessNanos(long d, long m) { return 0; }
 115     },
 116     MINUTES {
 117         public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
 118         public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
 119         public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
 120         public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
 121         public long toMinutes(long d) { return d; }
 122         public long toHours(long d)   { return d/(C5/C4); }
 123         public long toDays(long d)    { return d/(C6/C4); }
 124         public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
 125         int excessNanos(long d, long m) { return 0; }
 126     },
 127     HOURS {
 128         public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
 129         public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
 130         public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
 131         public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
 132         public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
 133         public long toHours(long d)   { return d; }
 134         public long toDays(long d)    { return d/(C6/C5); }
 135         public long convert(long d, TimeUnit u) { return u.toHours(d); }
 136         int excessNanos(long d, long m) { return 0; }
 137     },
 138     DAYS {
 139         public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
 140         public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
 141         public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
 142         public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
 143         public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
 144         public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
 145         public long toDays(long d)    { return d; }
 146         public long convert(long d, TimeUnit u) { return u.toDays(d); }
 147         int excessNanos(long d, long m) { return 0; }
 148     };
 149 
 150     // Handy constants for conversion methods
 151     static final long C0 = 1L;
 152     static final long C1 = C0 * 1000L;
 153     static final long C2 = C1 * 1000L;
 154     static final long C3 = C2 * 1000L;
 155     static final long C4 = C3 * 60L;
 156     static final long C5 = C4 * 60L;
 157     static final long C6 = C5 * 24L;
 158 
 159     static final long MAX = Long.MAX_VALUE;
 160 
 161     /**
 162      * Scale d by m, checking for overflow.
 163      * This has a short name to make above code more readable.
 164      */
 165     static long x(long d, long m, long over) {
 166         if (d >  over) return Long.MAX_VALUE;
 167         if (d < -over) return Long.MIN_VALUE;
 168         return d * m;
 169     }
 170 
 171     // To maintain full signature compatibility with 1.5, and to improve the
 172     // clarity of the generated javadoc (see 6287639: Abstract methods in
 173     // enum classes should not be listed as abstract), method convert
 174     // etc. are not declared abstract but otherwise act as abstract methods.
 175 
 176     /**
 177      * Convert the given time duration in the given unit to this
 178      * unit.  Conversions from finer to coarser granularities
 179      * truncate, so lose precision. For example converting
 180      * <tt>999</tt> milliseconds to seconds results in
 181      * <tt>0</tt>. Conversions from coarser to finer granularities
 182      * with arguments that would numerically overflow saturate to
 183      * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
 184      * if positive.
 185      *
 186      * <p>For example, to convert 10 minutes to milliseconds, use:
 187      * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
 188      *
 189      * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
 190      * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
 191      * @return the converted duration in this unit,
 192      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
 193      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
 194      */
 195     public long convert(long sourceDuration, TimeUnit sourceUnit) {
 196         throw new AbstractMethodError();
 197     }
 198 
 199     /**
 200      * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
 201      * @param duration the duration
 202      * @return the converted duration,
 203      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
 204      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
 205      * @see #convert
 206      */
 207     public long toNanos(long duration) {
 208         throw new AbstractMethodError();
 209     }
 210 
 211     /**
 212      * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
 213      * @param duration the duration
 214      * @return the converted duration,
 215      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
 216      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
 217      * @see #convert
 218      */
 219     public long toMicros(long duration) {
 220         throw new AbstractMethodError();
 221     }
 222 
 223     /**
 224      * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
 225      * @param duration the duration
 226      * @return the converted duration,
 227      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
 228      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
 229      * @see #convert
 230      */
 231     public long toMillis(long duration) {
 232         throw new AbstractMethodError();
 233     }
 234 
 235     /**
 236      * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
 237      * @param duration the duration
 238      * @return the converted duration,
 239      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
 240      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
 241      * @see #convert
 242      */
 243     public long toSeconds(long duration) {
 244         throw new AbstractMethodError();
 245     }
 246 
 247     /**
 248      * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
 249      * @param duration the duration
 250      * @return the converted duration,
 251      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
 252      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
 253      * @see #convert
 254      * @since 1.6
 255      */
 256     public long toMinutes(long duration) {
 257         throw new AbstractMethodError();
 258     }
 259 
 260     /**
 261      * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
 262      * @param duration the duration
 263      * @return the converted duration,
 264      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
 265      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
 266      * @see #convert
 267      * @since 1.6
 268      */
 269     public long toHours(long duration) {
 270         throw new AbstractMethodError();
 271     }
 272 
 273     /**
 274      * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
 275      * @param duration the duration
 276      * @return the converted duration
 277      * @see #convert
 278      * @since 1.6
 279      */
 280     public long toDays(long duration) {
 281         throw new AbstractMethodError();
 282     }
 283 
 284     /**
 285      * Utility to compute the excess-nanosecond argument to wait,
 286      * sleep, join.
 287      * @param d the duration
 288      * @param m the number of milliseconds
 289      * @return the number of nanoseconds
 290      */
 291     abstract int excessNanos(long d, long m);
 292 
 293     /**
 294      * Performs a timed <tt>Object.wait</tt> using this time unit.
 295      * This is a convenience method that converts timeout arguments
 296      * into the form required by the <tt>Object.wait</tt> method.
 297      *
 298      * <p>For example, you could implement a blocking <tt>poll</tt>
 299      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
 300      * using:
 301      *
 302      * <pre>  public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
 303      *    while (empty) {
 304      *      unit.timedWait(this, timeout);
 305      *      ...
 306      *    }
 307      *  }</pre>
 308      *
 309      * @param obj the object to wait on
 310      * @param timeout the maximum time to wait. If less than
 311      * or equal to zero, do not wait at all.
 312      * @throws InterruptedException if interrupted while waiting.
 313      * @see Object#wait(long, int)
 314      */
 315     public void timedWait(Object obj, long timeout)
 316     throws InterruptedException {
 317         if (timeout > 0) {
 318             long ms = toMillis(timeout);
 319             int ns = excessNanos(timeout, ms);
 320             obj.wait(ms, ns);
 321         }
 322     }
 323 
 324     /**
 325      * Performs a timed <tt>Thread.join</tt> using this time unit.
 326      * This is a convenience method that converts time arguments into the
 327      * form required by the <tt>Thread.join</tt> method.
 328      * @param thread the thread to wait for
 329      * @param timeout the maximum time to wait. If less than
 330      * or equal to zero, do not wait at all.
 331      * @throws InterruptedException if interrupted while waiting.
 332      * @see Thread#join(long, int)
 333      */
 334     public void timedJoin(Thread thread, long timeout)
 335     throws InterruptedException {
 336         if (timeout > 0) {
 337             long ms = toMillis(timeout);
 338             int ns = excessNanos(timeout, ms);
 339             thread.join(ms, ns);
 340         }
 341     }
 342 
 343     /**
 344      * Performs a <tt>Thread.sleep</tt> using this unit.
 345      * This is a convenience method that converts time arguments into the
 346      * form required by the <tt>Thread.sleep</tt> method.
 347      * @param timeout the minimum time to sleep. If less than
 348      * or equal to zero, do not sleep at all.
 349      * @throws InterruptedException if interrupted while sleeping.
 350      * @see Thread#sleep
 351      */
 352     public void sleep(long timeout) throws InterruptedException {
 353         if (timeout > 0) {
 354             long ms = toMillis(timeout);
 355             int ns = excessNanos(timeout, ms);
 356             Thread.sleep(ms, ns);
 357         }
 358     }
 359 
 360 }