22
22
*/
23
23
package net .tascalate .concurrent ;
24
24
25
+ import java .util .Collection ;
25
26
import java .util .LinkedList ;
26
27
import java .util .Objects ;
27
- import java .util .Queue ;
28
28
import java .util .concurrent .Callable ;
29
29
import java .util .concurrent .CompletableFuture ;
30
30
import java .util .concurrent .Executor ;
31
31
import java .util .concurrent .RejectedExecutionException ;
32
- import java .util .function .Consumer ;
32
+ import java .util .function .BiConsumer ;
33
33
import java .util .function .Function ;
34
34
35
35
class CallbackRegistry <T > {
36
- private State <T > state = InitialState .instance ();
37
-
38
36
private final Object mutex = new Object ();
39
-
37
+ private State <T > state = InitialState .instance ();
38
+
40
39
/**
41
40
* Adds the given callbacks to this registry.
42
41
*/
43
- <U > void addCallbacks (Consumer <? super Callable < U >> stageTransition ,
42
+ <U > void addCallbacks (AbstractCompletableTask < U > target ,
44
43
Function <? super T , ? extends U > successCallback ,
45
44
Function <Throwable , ? extends U > failureCallback ,
46
45
Executor executor ) {
@@ -49,11 +48,8 @@ <U> void addCallbacks(Consumer<? super Callable<U>> stageTransition,
49
48
Objects .requireNonNull (failureCallback , "'failureCallback' must not be null" );
50
49
Objects .requireNonNull (executor , "'executor' must not be null" );
51
50
52
- @ SuppressWarnings ("unchecked" )
53
- Consumer <? super Callable <?>> typedTransition = (Consumer <? super Callable <?>>)stageTransition ;
54
-
55
51
synchronized (mutex ) {
56
- state = state .addCallbacks (typedTransition , successCallback , failureCallback , executor );
52
+ state = state .addCallbacks (target , successCallback , failureCallback , executor );
57
53
}
58
54
}
59
55
@@ -114,11 +110,11 @@ boolean isCompleted() {
114
110
* State of the registry. All subclasses are meant to be used form a
115
111
* synchronized block and are NOT thread safe on their own.
116
112
*/
117
- private static abstract class State <S > {
118
- protected abstract State <S > addCallbacks (Consumer <? super Callable <?>> stageTransition ,
119
- Function <? super S , ?> successCallback ,
120
- Function <Throwable , ?> failureCallback ,
121
- Executor executor );
113
+ static abstract class State <S > {
114
+ protected abstract < U > State <S > addCallbacks (AbstractCompletableTask < U > target ,
115
+ Function <? super S , ? extends U > successCallback ,
116
+ Function <Throwable , ? extends U > failureCallback ,
117
+ Executor executor );
122
118
123
119
protected State <S > getSuccessState (S result ) {
124
120
throw new IllegalStateException ("success method should not be called multiple times" );
@@ -147,17 +143,17 @@ protected boolean isFailure() {
147
143
* Result is not known yet and no callbacks registered. Using shared
148
144
* instance so we do not allocate instance where it may not be needed.
149
145
*/
150
- private static class InitialState <S > extends State <S > {
146
+ static class InitialState <S > extends State <S > {
151
147
private static final InitialState <Object > instance = new InitialState <>();
152
148
153
149
@ Override
154
- protected State <S > addCallbacks (Consumer <? super Callable <?>> stageTransition ,
155
- Function <? super S , ?> successCallback ,
156
- Function <Throwable , ?> failureCallback ,
157
- Executor executor ) {
150
+ protected < U > State <S > addCallbacks (AbstractCompletableTask < U > target ,
151
+ Function <? super S , ? extends U > successCallback ,
152
+ Function <Throwable , ? extends U > failureCallback ,
153
+ Executor executor ) {
158
154
159
155
IntermediateState <S > intermediateState = new IntermediateState <>();
160
- intermediateState .addCallbacks (stageTransition , successCallback , failureCallback , executor );
156
+ intermediateState .addCallbacks (target , successCallback , failureCallback , executor );
161
157
return intermediateState ;
162
158
}
163
159
@@ -177,24 +173,30 @@ protected boolean isCompleted() {
177
173
}
178
174
179
175
@ SuppressWarnings ("unchecked" )
180
- private static <T > State <T > instance () {
176
+ static <T > State <T > instance () {
181
177
return (State <T >) instance ;
182
178
}
183
179
}
184
180
185
181
/**
186
182
* Result is not known yet.
187
183
*/
188
- private static class IntermediateState <S > extends State <S > {
189
- private final Queue < CallbackHolder <? super S >> callbacks = new LinkedList <>();
184
+ static class IntermediateState <S > extends State <S > {
185
+ private final Collection < BiConsumer <? super S , ? super Throwable >> callbacks = new LinkedList <>();
190
186
191
187
@ Override
192
- protected State <S > addCallbacks (Consumer <? super Callable <?>> stageTransition ,
193
- Function <? super S , ?> successCallback ,
194
- Function <Throwable , ?> failureCallback ,
195
- Executor executor ) {
188
+ protected < U > State <S > addCallbacks (AbstractCompletableTask < U > target ,
189
+ Function <? super S , ? extends U > successCallback ,
190
+ Function <Throwable , ? extends U > failureCallback ,
191
+ Executor executor ) {
196
192
197
- callbacks .add (new CallbackHolder <>(stageTransition , successCallback , failureCallback , executor ));
193
+ callbacks .add ((r , e ) -> {
194
+ if (null == e ) {
195
+ callCallback (target , successCallback , r , executor );
196
+ } else {
197
+ callCallback (target , failureCallback , e , executor );
198
+ }
199
+ });
198
200
return this ;
199
201
}
200
202
@@ -205,10 +207,8 @@ protected State<S> getSuccessState(S result) {
205
207
206
208
@ Override
207
209
protected void callSuccessCallbacks (S result ) {
208
- // no need to remove callbacks from the queue, this instance will be
209
- // thrown away at once
210
- for (CallbackHolder <? super S > callback : callbacks ) {
211
- callback .callSuccessCallback (result );
210
+ for (BiConsumer <? super S , ? super Throwable > callback : callbacks ) {
211
+ callback .accept (result , null );
212
212
}
213
213
}
214
214
@@ -219,10 +219,8 @@ protected State<S> getFailureState(Throwable failure) {
219
219
220
220
@ Override
221
221
protected void callFailureCallbacks (Throwable failure ) {
222
- // no need to remove callbacks from the queue, this instance will be
223
- // thrown away at once
224
- for (CallbackHolder <? super S > callback : callbacks ) {
225
- callback .callFailureCallback (failure );
222
+ for (BiConsumer <? super S , ? super Throwable > callback : callbacks ) {
223
+ callback .accept (null , failure );
226
224
}
227
225
}
228
226
@@ -235,41 +233,39 @@ protected boolean isCompleted() {
235
233
/**
236
234
* Holds the result.
237
235
*/
238
- private static final class SuccessState <S > extends State <S > {
236
+ static final class SuccessState <S > extends State <S > {
239
237
private final S result ;
240
238
241
- private SuccessState (S result ) {
239
+ SuccessState (S result ) {
242
240
this .result = result ;
243
241
}
244
242
245
243
@ Override
246
- protected State <S > addCallbacks (Consumer <? super Callable <?>> stageTransition ,
247
- Function <? super S , ?> successCallback ,
248
- Function <Throwable , ?> failureCallback ,
249
- Executor executor ) {
250
-
251
- callCallback (stageTransition , successCallback , result , executor );
244
+ protected <U > State <S > addCallbacks (AbstractCompletableTask <U > target ,
245
+ Function <? super S , ? extends U > successCallback ,
246
+ Function <Throwable , ? extends U > failureCallback ,
247
+ Executor executor ) {
248
+ callCallback (target , successCallback , result , executor );
252
249
return this ;
253
250
}
254
251
}
255
252
256
253
/**
257
254
* Holds the failure.
258
255
*/
259
- private static final class FailureState <S > extends State <S > {
256
+ static final class FailureState <S > extends State <S > {
260
257
private final Throwable failure ;
261
258
262
- private FailureState (Throwable failure ) {
259
+ FailureState (Throwable failure ) {
263
260
this .failure = failure ;
264
261
}
265
262
266
263
@ Override
267
- protected State <S > addCallbacks (Consumer <? super Callable <?>> stageTransition ,
268
- Function <? super S , ?> successCallback ,
269
- Function <Throwable , ?> failureCallback ,
270
- Executor executor ) {
271
-
272
- callCallback (stageTransition , failureCallback , failure , executor );
264
+ protected <U > State <S > addCallbacks (AbstractCompletableTask <U > target ,
265
+ Function <? super S , ? extends U > successCallback ,
266
+ Function <Throwable , ? extends U > failureCallback ,
267
+ Executor executor ) {
268
+ callCallback (target , failureCallback , failure , executor );
273
269
return this ;
274
270
}
275
271
@@ -278,47 +274,21 @@ protected boolean isFailure() {
278
274
}
279
275
}
280
276
281
- private static final class CallbackHolder <S > {
282
- private final Consumer <? super Callable <?>> stageTransition ;
283
- private final Function <? super S , ?> successCallback ;
284
- private final Function <Throwable , ?> failureCallback ;
285
- private final Executor executor ;
286
-
287
- private CallbackHolder (Consumer <? super Callable <?>> stageTransition ,
288
- Function <? super S , ?> successCallback ,
289
- Function <Throwable , ?> failureCallback ,
290
- Executor executor ) {
291
-
292
- this .stageTransition = stageTransition ;
293
- this .successCallback = successCallback ;
294
- this .failureCallback = failureCallback ;
295
- this .executor = executor ;
296
- }
297
-
298
- void callSuccessCallback (S result ) {
299
- callCallback (stageTransition , successCallback , result , executor );
300
- }
301
-
302
- void callFailureCallback (Throwable failure ) {
303
- callCallback (stageTransition , failureCallback , failure , executor );
304
- }
305
- }
306
-
307
- private static <S , U > void callCallback (Consumer <? super Callable <?>> stageTransition ,
308
- Function <? super S , ? extends U > callback ,
309
- S value ,
310
- Executor executor ) {
277
+ static <T , U > void callCallback (AbstractCompletableTask <U > target ,
278
+ Function <? super T , ? extends U > callback ,
279
+ T value ,
280
+ Executor executor ) {
311
281
312
282
Callable <U > callable = () -> callback .apply (value );
313
283
try {
314
- executor .execute ( (AsyncTask )() -> stageTransition . accept (callable ) );
284
+ executor .execute ( (AsyncTask )() -> target . fireTransition (callable ) );
315
285
} catch (RejectedExecutionException ex ) {
316
286
// Propagate error in-place
317
287
Callable <U > propagateError = () -> { throw ex ; };
318
- stageTransition . accept (propagateError );
288
+ target . fireTransition (propagateError );
319
289
}
320
290
}
321
-
291
+
322
292
@ FunctionalInterface
323
293
static interface AsyncTask extends Runnable , CompletableFuture .AsynchronousCompletionTask {}
324
294
0 commit comments