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 }