1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.core5.concurrent;
28
29 import java.util.concurrent.CancellationException;
30 import java.util.concurrent.ExecutionException;
31 import java.util.concurrent.Future;
32 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.TimeoutException;
34
35 import org.apache.hc.core5.util.Args;
36 import org.apache.hc.core5.util.TimeoutValueException;
37
38
39
40
41
42
43
44
45
46 public class BasicFuture<T> implements Future<T>, Cancellable {
47
48 private final FutureCallback<T> callback;
49
50 private volatile boolean completed;
51 private volatile boolean cancelled;
52 private volatile T result;
53 private volatile Exception ex;
54
55 public BasicFuture(final FutureCallback<T> callback) {
56 super();
57 this.callback = callback;
58 }
59
60 @Override
61 public boolean isCancelled() {
62 return this.cancelled;
63 }
64
65 @Override
66 public boolean isDone() {
67 return this.completed;
68 }
69
70 private T getResult() throws ExecutionException {
71 if (this.ex != null) {
72 throw new ExecutionException(this.ex);
73 }
74 if (cancelled) {
75 throw new CancellationException();
76 }
77 return this.result;
78 }
79
80 @Override
81 public synchronized T get() throws InterruptedException, ExecutionException {
82 while (!this.completed) {
83 wait();
84 }
85 return getResult();
86 }
87
88 @Override
89 public synchronized T get(final long timeout, final TimeUnit unit)
90 throws InterruptedException, ExecutionException, TimeoutException {
91 Args.notNull(unit, "Time unit");
92 final long msecs = unit.toMillis(timeout);
93 final long startTime = (msecs <= 0) ? 0 : System.currentTimeMillis();
94 long waitTime = msecs;
95 if (this.completed) {
96 return getResult();
97 } else if (waitTime <= 0) {
98 throw TimeoutValueException.fromMilliseconds(msecs, msecs + Math.abs(waitTime));
99 } else {
100 for (;;) {
101 wait(waitTime);
102 if (this.completed) {
103 return getResult();
104 }
105 waitTime = msecs - (System.currentTimeMillis() - startTime);
106 if (waitTime <= 0) {
107 throw TimeoutValueException.fromMilliseconds(msecs, msecs + Math.abs(waitTime));
108 }
109 }
110 }
111 }
112
113 public boolean completed(final T result) {
114 synchronized(this) {
115 if (this.completed) {
116 return false;
117 }
118 this.completed = true;
119 this.result = result;
120 notifyAll();
121 }
122 if (this.callback != null) {
123 this.callback.completed(result);
124 }
125 return true;
126 }
127
128 public boolean failed(final Exception exception) {
129 synchronized(this) {
130 if (this.completed) {
131 return false;
132 }
133 this.completed = true;
134 this.ex = exception;
135 notifyAll();
136 }
137 if (this.callback != null) {
138 this.callback.failed(exception);
139 }
140 return true;
141 }
142
143 @Override
144 public boolean cancel(final boolean mayInterruptIfRunning) {
145 synchronized(this) {
146 if (this.completed) {
147 return false;
148 }
149 this.completed = true;
150 this.cancelled = true;
151 notifyAll();
152 }
153 if (this.callback != null) {
154 this.callback.cancelled();
155 }
156 return true;
157 }
158
159 @Override
160 public boolean cancel() {
161 return cancel(true);
162 }
163
164 }