1e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/* 2e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Copyright (C) 2014 Square, Inc. 3e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 4e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 5e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * you may not use this file except in compliance with the License. 6e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * You may obtain a copy of the License at 7e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 8e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * http://www.apache.org/licenses/LICENSE-2.0 9e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 10e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Unless required by applicable law or agreed to in writing, software 11e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 12e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * See the License for the specific language governing permissions and 14e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * limitations under the License. 15e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 16e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpackage okio; 17e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 18e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.IOException; 19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.InterruptedIOException; 20e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.concurrent.TimeUnit; 21e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 22e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/** 23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * A policy on how much time to spend on a task before giving up. When a task 24e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * times out, it is left in an unspecified state and should be abandoned. For 25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * example, if reading from a source times out, that source should be closed and 26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * the read should be retried later. If writing to a sink times out, the same 27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * rules apply: close the sink and retry later. 28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * <h3>Timeouts and Deadlines</h3> 30e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * This class offers two complementary controls to define a timeout policy. 31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * <p><strong>Timeouts</strong> specify the maximum time to wait for a single 33e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * operation to complete. Timeouts are typically used to detect problems like 34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * network partitions. For example, if a remote peer doesn't return <i>any</i> 35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * data for ten seconds, we may assume that the peer is unavailable. 36e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 37e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * <p><strong>Deadlines</strong> specify the maximum time to spend on a job, 38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * composed of one or more operations. Use deadlines to set an upper bound on 39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * the time invested on a job. For example, a battery-conscious app may limit 40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * how much time it spends preloading content. 41e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 42e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic class Timeout { 43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * An empty timeout that neither tracks nor detects timeouts. Use this when 45e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * timeouts aren't necessary, such as in implementations whose operations 46e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * do not block. 47e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 48e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public static final Timeout NONE = new Timeout() { 49e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public Timeout timeout(long timeout, TimeUnit unit) { 50e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return this; 51e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 52e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 53e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public Timeout deadlineNanoTime(long deadlineNanoTime) { 54e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return this; 55e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 56e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 57e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public void throwIfReached() throws IOException { 58e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 59e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }; 60e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 61e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 62e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * True if {@code deadlineNanoTime} is defined. There is no equivalent to null 63e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * or 0 for {@link System#nanoTime}. 64e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private boolean hasDeadline; 66e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private long deadlineNanoTime; 67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private long timeoutNanos; 68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 69e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public Timeout() { 70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 72e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Wait at most {@code timeout} time before aborting an operation. Using a 74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * per-operation timeout means that as long as forward progress is being made, 75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * no sequence of operations will fail. 76e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 77e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * <p>If {@code timeout == 0}, operations will run indefinitely. (Operating 78e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * system timeouts may still apply.) 79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 80e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public Timeout timeout(long timeout, TimeUnit unit) { 81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (timeout < 0) throw new IllegalArgumentException("timeout < 0: " + timeout); 82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (unit == null) throw new IllegalArgumentException("unit == null"); 83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller this.timeoutNanos = unit.toNanos(timeout); 84e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return this; 85e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 87e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Returns the timeout in nanoseconds, or {@code 0} for no timeout. */ 88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public long timeoutNanos() { 89e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return timeoutNanos; 90e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Returns true if a deadline is enabled. */ 93e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public boolean hasDeadline() { 94e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return hasDeadline; 95e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 97e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 98e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Returns the {@linkplain System#nanoTime() nano time} when the deadline will 99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * be reached. 100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * @throws IllegalStateException if no deadline is set. 102e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public long deadlineNanoTime() { 104e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (!hasDeadline) throw new IllegalStateException("No deadline"); 105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return deadlineNanoTime; 106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 108e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Sets the {@linkplain System#nanoTime() nano time} when the deadline will be 110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * reached. All operations must complete before this time. Use a deadline to 111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * set a maximum bound on the time spent on a sequence of operations. 112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public Timeout deadlineNanoTime(long deadlineNanoTime) { 114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller this.hasDeadline = true; 115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller this.deadlineNanoTime = deadlineNanoTime; 116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return this; 117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Set a deadline of now plus {@code duration} time. */ 120e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public final Timeout deadline(long duration, TimeUnit unit) { 121e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (duration <= 0) throw new IllegalArgumentException("duration <= 0: " + duration); 122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (unit == null) throw new IllegalArgumentException("unit == null"); 123e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return deadlineNanoTime(System.nanoTime() + unit.toNanos(duration)); 124e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 125e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 126e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Clears the timeout. Operating system timeouts may still apply. */ 127e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public Timeout clearTimeout() { 128e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller this.timeoutNanos = 0; 129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return this; 130e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 131e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 132e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Clears the deadline. */ 133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public Timeout clearDeadline() { 134e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller this.hasDeadline = false; 135e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return this; 136e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 138e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 139ed078614cd7c89aae39dce0615f8cbbf955b2a90Neil Fuller * Throws an {@link InterruptedIOException} if the deadline has been reached or if the current 140ed078614cd7c89aae39dce0615f8cbbf955b2a90Neil Fuller * thread has been interrupted. This method doesn't detect timeouts; that should be implemented to 141ed078614cd7c89aae39dce0615f8cbbf955b2a90Neil Fuller * asynchronously abort an in-progress operation. 142e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public void throwIfReached() throws IOException { 144e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (Thread.interrupted()) { 145ed078614cd7c89aae39dce0615f8cbbf955b2a90Neil Fuller throw new InterruptedIOException("thread interrupted"); 146e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 147e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 148ed078614cd7c89aae39dce0615f8cbbf955b2a90Neil Fuller if (hasDeadline && deadlineNanoTime - System.nanoTime() <= 0) { 149ed078614cd7c89aae39dce0615f8cbbf955b2a90Neil Fuller throw new InterruptedIOException("deadline reached"); 150e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 151e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 152e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller} 153