View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 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.util;
20  
21  import java.util.concurrent.atomic.AtomicBoolean;
22  
23  /**
24   * A callback to be used by driver code that needs to know whether the callback has been
25   * succeeded or failed (that is, completed) just after the asynchronous operation or not,
26   * typically because further processing depends on the callback being completed.
27   * The driver code competes with the asynchronous operation to complete the callback.
28   * <p />
29   * If the callback is already completed, the driver code continues the processing,
30   * otherwise it suspends it. If it is suspended, the callback will be completed some time
31   * later, and {@link #resume()} or {@link #abort(Throwable)} will be called to allow the
32   * application to resume the processing.
33   * <p />
34   * Typical usage:
35   * <pre>
36   * CompletableCallback callback = new CompletableCallback()
37   * {
38   *     &#64;Override
39   *     public void resume()
40   *     {
41   *         // continue processing
42   *     }
43   *
44   *     &#64;Override
45   *     public void abort(Throwable failure)
46   *     {
47   *         // abort processing
48   *     }
49   * }
50   * asyncOperation(callback);
51   * boolean completed = callback.tryComplete();
52   * if (completed)
53   *     // suspend processing, async operation not done yet
54   * else
55   *     // continue processing, async operation already done
56   * </pre>
57   */
58  public abstract class CompletableCallback implements Callback
59  {
60      private final AtomicBoolean completed = new AtomicBoolean();
61  
62      @Override
63      public void succeeded()
64      {
65          if (!tryComplete())
66              resume();
67      }
68  
69      @Override
70      public void failed(Throwable x)
71      {
72          if (!tryComplete())
73              abort(x);
74      }
75  
76      /**
77       * Callback method invoked when this callback is succeeded
78       * <em>after</em> a first call to {@link #tryComplete()}.
79       */
80      public abstract void resume();
81  
82      /**
83       * Callback method invoked when this callback is failed
84       * <em>after</em> a first call to {@link #tryComplete()}.
85       */
86      public abstract void abort(Throwable failure);
87  
88      /**
89       * Tries to complete this callback; driver code should call
90       * this method once <em>after</em> the asynchronous operation
91       * to detect whether the asynchronous operation has already
92       * completed or not.
93       *
94       * @return whether the attempt to complete was successful.
95       */
96      public boolean tryComplete()
97      {
98          return completed.compareAndSet(false, true);
99      }
100 }