1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util;
20
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;
26
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29 import org.eclipse.jetty.util.thread.NonBlockingThread;
30
31
32
33
34
35 public class BlockingCallback implements Callback
36 {
37 private static final Logger LOG = Log.getLogger(BlockingCallback.class);
38
39 private static Throwable SUCCEEDED=new Throwable()
40 {
41 @Override
42 public String toString() { return "SUCCEEDED"; }
43 };
44
45 private final CountDownLatch _latch = new CountDownLatch(1);
46 private final AtomicReference<Throwable> _state = new AtomicReference<>();
47
48 public BlockingCallback()
49 {}
50
51 @Override
52 public void succeeded()
53 {
54 if (_state.compareAndSet(null,SUCCEEDED))
55 _latch.countDown();
56 }
57
58 @Override
59 public void failed(Throwable cause)
60 {
61 if (_state.compareAndSet(null,cause))
62 _latch.countDown();
63 }
64
65
66
67
68
69
70
71 public void block() throws IOException
72 {
73 if (NonBlockingThread.isNonBlockingThread())
74 LOG.warn("Blocking a NonBlockingThread: ",new Throwable());
75
76 try
77 {
78 _latch.await();
79 Throwable state=_state.get();
80 if (state==SUCCEEDED)
81 return;
82 if (state instanceof IOException)
83 throw (IOException) state;
84 if (state instanceof CancellationException)
85 throw (CancellationException) state;
86 throw new IOException(state);
87 }
88 catch (final InterruptedException e)
89 {
90 throw new InterruptedIOException(){{initCause(e);}};
91 }
92 finally
93 {
94 _state.set(null);
95 }
96 }
97
98
99 @Override
100 public String toString()
101 {
102 return String.format("%s@%x{%s}",BlockingCallback.class.getSimpleName(),hashCode(),_state.get());
103 }
104
105 }