All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.atlassian.util.concurrent.Timeout Maven / Gradle / Ivy

Go to download

This project contains utility classes that are used by various products and projects inside Atlassian and may have some utility to the world at large.

The newest version!
/**
 * Copyright 2008 Atlassian Pty Ltd 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package io.atlassian.util.concurrent;

import net.jcip.annotations.Immutable;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;

/**
 * Automatically calculates elapsed time from when it is created. Useful when
 * successively calling blocking methods and a time since call time needs to be
 * worked out.
 * 

* Usage: * *

 * Timeout timeout = Timeout.getNanosTimeout(1, TimeUnit.SECONDS);
 * String str = futureString.get(timeout.getTime(), timeout.getUnit());
 * Integer num = futureInt.get(timeout.getTime(), timeout.getUnit());
 * 
* * where if the first call takes quarter of a second, the second call is passed * the equivalent of three-quarters of a second. */ @Immutable public final class Timeout { /** * Get a {@link io.atlassian.util.concurrent.Timeout} that uses nanosecond * precision. The accuracy will depend on the accuracy of * {@link java.lang.System#nanoTime()}. * * @param time the maximum time to wait for the lock * @param unit the time unit of the time argument. * @return timeout with {@link java.util.concurrent.TimeUnit#NANOSECONDS} * precision. */ public static Timeout getNanosTimeout(final long time, final TimeUnit unit) { return new Timeout(time, unit, TimeSuppliers.NANOS); } /** * Get a {@link io.atlassian.util.concurrent.Timeout} that uses millisecond * precision. The accuracy will depend on the accuracy of * {@link java.lang.System#currentTimeMillis()}. * * @param time the maximum time to wait for the lock * @param unit the time unit of the time argument. * @return timeout with {@link java.util.concurrent.TimeUnit#MILLISECONDS} * precision. */ public static Timeout getMillisTimeout(final long time, final TimeUnit unit) { return new Timeout(time, unit, TimeSuppliers.MILLIS); } /** * Factory for creating timeouts of the specified duration. Each * {@link io.atlassian.util.concurrent.Timeout} will start when the factory is * called. *

* Generally, use the {@link #getMillisTimeout(long, TimeUnit)} or * {@link #getNanosTimeout(long, TimeUnit)} factory methods directly. Only use * this if a custom {@link io.atlassian.util.concurrent.Timeout.TimeSupplier} * is required – for instance for testing, you can use this to mock out the * actual passage of time. * * @param time how long the timeouts should be for * @param unit in what units time is expressed in * @param supplier the thing that tells the timeout what the current time is. * @since 2.2 * @return a {@link java.util.function.Supplier}. */ public static Supplier timeoutFactory(final long time, final TimeUnit unit, final TimeSupplier supplier) { return () -> new Timeout(time, unit, supplier); } // // members // private final long created; private final long timeoutPeriod; private final TimeSupplier supplier; // // ctors // Timeout(final long time, final TimeUnit unit, final TimeSupplier supplier) { created = supplier.currentTime(); this.supplier = supplier; timeoutPeriod = this.supplier.precision().convert(time, unit); } // // methods // /** * Get time remaining * * @return a long. */ public long getTime() { return (created + timeoutPeriod) - supplier.currentTime(); } /** * Get the precision of this timeout. * * @return a {@link java.util.concurrent.TimeUnit}. */ public TimeUnit getUnit() { return supplier.precision(); } /** * Has this timeout expired * * @return true if expired */ public boolean isExpired() { return getTime() <= 0; } /** * The original timeout period expressed in {@link #getUnit() units} * * @since 2.2 * @return a long. */ public long getTimeoutPeriod() { return timeoutPeriod; } // // util // void await(final Awaitable waitable) throws TimeoutException, InterruptedException { if (!waitable.await(getTime(), getUnit())) { throwTimeoutException(); } } /** * Always throws a {@link java.util.concurrent.TimeoutException}. * * @throws io.atlassian.util.concurrent.TimedOutException if any. */ public void throwTimeoutException() throws TimedOutException { throw new TimedOutException(timeoutPeriod, getUnit()); } /** * Build a new time out exception for this timeout * * @return a {@link io.atlassian.util.concurrent.RuntimeTimeoutException}. */ public RuntimeTimeoutException getTimeoutException() { return new RuntimeTimeoutException(timeoutPeriod, getUnit()); } // // inners // /** * Supply time and precision to a {@link Timeout}. * * @since 2.2 */ public interface TimeSupplier { /** * The time now. */ long currentTime(); /** * The precision that the time is expressed in. */ TimeUnit precision(); } /** * Default {@link TimeSupplier} implementations. */ enum TimeSuppliers implements TimeSupplier { NANOS { @Override public long currentTime() { return System.nanoTime(); } @Override public TimeUnit precision() { return TimeUnit.NANOSECONDS; } }, MILLIS { @Override public long currentTime() { return System.currentTimeMillis(); } @Override public TimeUnit precision() { return TimeUnit.MILLISECONDS; } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy