View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.spdy;
20  
21  import java.util.concurrent.CancellationException;
22  import java.util.concurrent.CountDownLatch;
23  import java.util.concurrent.ExecutionException;
24  import java.util.concurrent.Future;
25  import java.util.concurrent.TimeUnit;
26  import java.util.concurrent.TimeoutException;
27  
28  import org.eclipse.jetty.spdy.api.Handler;
29  
30  /**
31   * <p>A {@link Promise} is a {@link Future} that allows a result or a failure to be set,
32   * so that the {@link Future} will be {@link #isDone() done}.</p>
33   *
34   * @param <T> the type of the result object
35   */
36  public class Promise<T> implements Handler<T>, Future<T>
37  {
38      private final CountDownLatch latch = new CountDownLatch(1);
39      private boolean cancelled;
40      private Throwable failure;
41      private T promise;
42  
43      @Override
44      public void completed(T result)
45      {
46          this.promise = result;
47          latch.countDown();
48      }
49  
50      @Override
51      public void failed(T context, Throwable x)
52      {
53          this.failure = x;
54          latch.countDown();
55      }
56  
57      @Override
58      public boolean cancel(boolean mayInterruptIfRunning)
59      {
60          cancelled = true;
61          latch.countDown();
62          return true;
63      }
64  
65      @Override
66      public boolean isCancelled()
67      {
68          return cancelled;
69      }
70  
71      @Override
72      public boolean isDone()
73      {
74          return cancelled || latch.getCount() == 0;
75      }
76  
77      @Override
78      public T get() throws InterruptedException, ExecutionException
79      {
80          latch.await();
81          return result();
82      }
83  
84      @Override
85      public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
86      {
87          boolean elapsed = !latch.await(timeout, unit);
88          if (elapsed)
89              throw new TimeoutException();
90          return result();
91      }
92  
93      private T result() throws ExecutionException
94      {
95          if (isCancelled())
96              throw new CancellationException();
97          Throwable failure = this.failure;
98          if (failure != null)
99              throw new ExecutionException(failure);
100         return promise;
101     }
102 }