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