2 // ========================================================================
3 // Copyright (c) 1995-2016 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.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.util;
21 import java.io.IOException;
22 import java.io.InterruptedIOException;
23 import java.util.concurrent.CancellationException;
24 import java.util.concurrent.CountDownLatch;
25 import java.util.concurrent.atomic.AtomicReference;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29 import org.eclipse.jetty.util.thread.NonBlockingThread;
31 /* ------------------------------------------------------------ */
33 * An implementation of Callback that blocks until success or failure.
35 public class BlockingCallback implements Callback
37 private static final Logger LOG = Log.getLogger(BlockingCallback.class);
39 private static Throwable SUCCEEDED=new Throwable()
42 public String toString() { return "SUCCEEDED"; }
45 private final CountDownLatch _latch = new CountDownLatch(1);
46 private final AtomicReference<Throwable> _state = new AtomicReference<>();
48 public BlockingCallback()
52 public void succeeded()
54 if (_state.compareAndSet(null,SUCCEEDED))
59 public void failed(Throwable cause)
61 if (_state.compareAndSet(null,cause))
65 /** Block until the Callback has succeeded or failed and
66 * after the return leave in the state to allow reuse.
67 * This is useful for code that wants to repeatable use a FutureCallback to convert
68 * an asynchronous API to a blocking API.
69 * @throws IOException if exception was caught during blocking, or callback was cancelled
71 public void block() throws IOException
73 if (NonBlockingThread.isNonBlockingThread())
74 LOG.warn("Blocking a NonBlockingThread: ",new Throwable());
79 Throwable state=_state.get();
82 if (state instanceof IOException)
83 throw (IOException) state;
84 if (state instanceof CancellationException)
85 throw (CancellationException) state;
86 throw new IOException(state);
88 catch (final InterruptedException e)
90 throw new InterruptedIOException(){{initCause(e);}};
100 public String toString()
102 return String.format("%s@%x{%s}",BlockingCallback.class.getSimpleName(),hashCode(),_state.get());