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 * @Override
39 * public void resume()
40 * {
41 * // continue processing
42 * }
43 *
44 * @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 }