1
1
/*
2
- * Copyright 2002-2016 the original author or authors.
2
+ * Copyright 2002-2017 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
27
27
28
28
/**
29
29
* A {@link org.springframework.util.concurrent.ListenableFuture ListenableFuture}
30
- * whose value can be set via {@link #set(Object )} or
31
- * {@link #setException(Throwable)}. It may also be cancelled.
30
+ * whose value can be set via {@link #set(T )} or {@link #setException(Throwable)}.
31
+ * It may also be cancelled.
32
32
*
33
33
* <p>Inspired by {@code com.google.common.util.concurrent.SettableFuture}.
34
34
*
35
35
* @author Mattias Severson
36
36
* @author Rossen Stoyanchev
37
+ * @author Juergen Hoeller
37
38
* @since 4.1
38
39
*/
39
40
public class SettableListenableFuture <T > implements ListenableFuture <T > {
@@ -92,8 +93,8 @@ public void addCallback(SuccessCallback<? super T> successCallback, FailureCallb
92
93
93
94
@ Override
94
95
public boolean cancel (boolean mayInterruptIfRunning ) {
95
- this .settableTask .setCancelled ();
96
- boolean cancelled = this .listenableFuture .cancel (mayInterruptIfRunning );
96
+ boolean cancelled = this .settableTask .setCancelled ();
97
+ this .listenableFuture .cancel (mayInterruptIfRunning );
97
98
if (cancelled && mayInterruptIfRunning ) {
98
99
interruptTask ();
99
100
}
@@ -102,21 +103,21 @@ public boolean cancel(boolean mayInterruptIfRunning) {
102
103
103
104
@ Override
104
105
public boolean isCancelled () {
105
- return this .listenableFuture .isCancelled ();
106
+ return this .settableTask .isCancelled ();
106
107
}
107
108
108
109
@ Override
109
110
public boolean isDone () {
110
- return this .listenableFuture .isDone ();
111
+ return this .settableTask .isDone ();
111
112
}
112
113
113
114
/**
114
115
* Retrieve the value.
115
- * <p>Will return the value if it has been set via {@link #set(Object)},
116
- * throw an {@link java.util.concurrent.ExecutionException} if it has been
117
- * set via {@link #setException(Throwable)} or throw a
118
- * {@link java.util.concurrent.CancellationException} if it has been cancelled.
119
- * @return The value associated with this future.
116
+ * <p>This method returns the value if it has been set via {@link #set(Object)},
117
+ * throws an {@link java.util.concurrent.ExecutionException} if an exception has
118
+ * been set via {@link #setException(Throwable)}, or throws a
119
+ * {@link java.util.concurrent.CancellationException} if the future has been cancelled.
120
+ * @return the value associated with this future
120
121
*/
121
122
@ Override
122
123
public T get () throws InterruptedException , ExecutionException {
@@ -125,13 +126,13 @@ public T get() throws InterruptedException, ExecutionException {
125
126
126
127
/**
127
128
* Retrieve the value.
128
- * <p>Will return the value if it has been set via {@link #set(Object)},
129
- * throw an {@link java.util.concurrent.ExecutionException} if it has been
130
- * set via {@link #setException(Throwable)} or throw a
131
- * {@link java.util.concurrent.CancellationException} if it has been cancelled.
132
- * @param timeout the maximum time to wait.
133
- * @param unit the time unit of the timeout argument.
134
- * @return The value associated with this future.
129
+ * <p>This method returns the value if it has been set via {@link #set(Object)},
130
+ * throws an {@link java.util.concurrent.ExecutionException} if an exception has
131
+ * been set via {@link #setException(Throwable)}, or throws a
132
+ * {@link java.util.concurrent.CancellationException} if the future has been cancelled.
133
+ * @param timeout the maximum time to wait
134
+ * @param unit the unit of the timeout argument
135
+ * @return the value associated with this future
135
136
*/
136
137
@ Override
137
138
public T get (long timeout , TimeUnit unit ) throws InterruptedException , ExecutionException , TimeoutException {
@@ -142,7 +143,7 @@ public T get(long timeout, TimeUnit unit) throws InterruptedException, Execution
142
143
* Subclasses can override this method to implement interruption of the future's
143
144
* computation. The method is invoked automatically by a successful call to
144
145
* {@link #cancel(boolean) cancel(true)}.
145
- * <p>The default implementation does nothing .
146
+ * <p>The default implementation is empty .
146
147
*/
147
148
protected void interruptTask () {
148
149
}
@@ -152,26 +153,28 @@ private static class SettableTask<T> implements Callable<T> {
152
153
153
154
private static final Object NO_VALUE = new Object ();
154
155
155
- private final AtomicReference < Object > value = new AtomicReference < Object >( NO_VALUE );
156
+ private static final Object CANCELLED = new Object ( );
156
157
157
- private volatile boolean cancelled = false ;
158
+ private final AtomicReference < Object > value = new AtomicReference < Object >( NO_VALUE ) ;
158
159
159
160
public boolean setValue (T value ) {
160
- if (this .cancelled ) {
161
- return false ;
162
- }
163
161
return this .value .compareAndSet (NO_VALUE , value );
164
162
}
165
163
166
164
public boolean setException (Throwable exception ) {
167
- if (this .cancelled ) {
168
- return false ;
169
- }
170
165
return this .value .compareAndSet (NO_VALUE , exception );
171
166
}
172
167
173
- public void setCancelled () {
174
- this .cancelled = true ;
168
+ public boolean setCancelled () {
169
+ return this .value .compareAndSet (NO_VALUE , CANCELLED );
170
+ }
171
+
172
+ public boolean isCancelled () {
173
+ return (this .value .get () == CANCELLED );
174
+ }
175
+
176
+ public boolean isDone () {
177
+ return (this .value .get () != NO_VALUE );
175
178
}
176
179
177
180
@ SuppressWarnings ("unchecked" )
0 commit comments