@@ -38,7 +38,7 @@ final class FutureImpl<T> implements Future<T> {
38
38
/**
39
39
* Used to start new threads.
40
40
*/
41
- private final ExecutorService executorService ;
41
+ private final Executor executor ;
42
42
43
43
/**
44
44
* Used to synchronize state changes.
@@ -64,24 +64,15 @@ final class FutureImpl<T> implements Future<T> {
64
64
@ GuardedBy ("lock" )
65
65
private Queue <Consumer <Try <T >>> actions ;
66
66
67
- /**
68
- * Once a computation is started via run(), job is defined and used to control the lifecycle of the computation.
69
- * <p>
70
- * The {@code java.util.concurrent.Future} is not intended to store the result of the computation, it is stored in
71
- * {@code value} instead.
72
- */
73
- @ GuardedBy ("lock" )
74
- private java .util .concurrent .Future <?> job ;
75
-
76
67
// single constructor
77
- private FutureImpl (ExecutorService executorService , Option <Try <T >> value , Queue <Consumer <Try <T >>> actions , CheckedFunction1 < FutureImpl < T >, java . util . concurrent . Future <?>> jobFactory ) {
78
- this .executorService = executorService ;
68
+ private FutureImpl (Executor executor , Option <Try <T >> value , Queue <Consumer <Try <T >>> actions , Computation < T > computation ) {
69
+ this .executor = executor ;
79
70
synchronized (lock ) {
80
71
this .cancelled = false ;
81
72
this .value = value ;
82
73
this .actions = actions ;
83
74
try {
84
- this . job = jobFactory . apply (this );
75
+ computation . execute (this :: tryComplete , this :: updateThread );
85
76
} catch (Throwable x ) {
86
77
tryComplete (Try .failure (x ));
87
78
}
@@ -91,46 +82,44 @@ private FutureImpl(ExecutorService executorService, Option<Try<T>> value, Queue<
91
82
/**
92
83
* Creates a {@code FutureImpl} that is immediately completed with the given value. No task will be started.
93
84
*
94
- * @param executorService An {@link ExecutorService } to run and control the computation and to perform the actions.
85
+ * @param executor An {@link Executor } to run and control the computation and to perform the actions.
95
86
* @param value the result of this Future
96
87
*/
97
88
@ SuppressWarnings ("unchecked" )
98
- static <T > FutureImpl <T > of (ExecutorService executorService , Try <? extends T > value ) {
99
- return new FutureImpl <>(executorService , Option .some (Try .narrow (value )), null , ignored -> null );
89
+ static <T > FutureImpl <T > of (Executor executor , Try <? extends T > value ) {
90
+ return new FutureImpl <>(executor , Option .some (Try .narrow (value )), null , ( tryComplete , updateThread ) -> {} );
100
91
}
101
92
102
93
/**
103
94
* Creates a {@code FutureImpl} that is eventually completed.
104
95
* The given {@code computation} is <em>synchronously</em> executed, no thread is started.
105
96
*
106
- * @param executorService An {@link ExecutorService } to run and control the computation and to perform the actions.
97
+ * @param executor An {@link Executor } to run and control the computation and to perform the actions.
107
98
* @param computation A non-blocking computation
108
99
* @param <T> value type of the Future
109
100
* @return a new {@code FutureImpl} instance
110
101
*/
111
- static <T > FutureImpl <T > sync (ExecutorService executorService , CheckedConsumer <Predicate <Try <? extends T >>> computation ) {
112
- return new FutureImpl <>(executorService , Option .none (), Queue .empty (), future -> {
113
- computation .accept (future ::tryComplete );
114
- return null ;
102
+ static <T > FutureImpl <T > sync (Executor executor , CheckedConsumer <Predicate <Try <? extends T >>> computation ) {
103
+ return new FutureImpl <>(executor , Option .none (), Queue .empty (), (tryComplete , updateThread ) -> {
104
+ computation .accept (tryComplete );
115
105
});
116
106
}
117
107
118
108
/**
119
109
* Creates a {@code FutureImpl} that is eventually completed.
120
110
* The given {@code computation} is <em>asynchronously</em> executed, a new thread is started.
121
111
*
122
- * @param executorService An {@link ExecutorService } to run and control the computation and to perform the actions.
112
+ * @param executor An {@link Executor } to run and control the computation and to perform the actions.
123
113
* @param computation A (possibly blocking) computation
124
114
* @param <T> value type of the Future
125
115
* @return a new {@code FutureImpl} instance
126
116
*/
127
- static <T > FutureImpl <T > async (ExecutorService executorService , CheckedConsumer <Predicate <Try <? extends T >>> computation ) {
128
- // In a single-threaded context this Future may already have been completed during initialization.
129
- return new FutureImpl <>(executorService , Option .none (), Queue .empty (), future -> executorService .submit (() -> {
117
+ static <T > FutureImpl <T > async (Executor executor , CheckedConsumer <Predicate <Try <? extends T >>> computation ) {
118
+ return new FutureImpl <>(executor , Option .none (), Queue .empty (), (tryComplete , updateThread ) -> executor .execute (() -> {
130
119
try {
131
- computation .accept (future :: tryComplete );
120
+ computation .accept (tryComplete );
132
121
} catch (Throwable x ) {
133
- future . tryComplete (Try .failure (x ));
122
+ tryComplete . test (Try .failure (x ));
134
123
}
135
124
}));
136
125
}
@@ -148,22 +137,17 @@ public Future<T> await(long timeout, TimeUnit unit) {
148
137
@ Override
149
138
public Future <T > cancel (boolean mayInterruptIfRunning ) {
150
139
if (!isCompleted ()) {
151
- synchronized (lock ) {
152
- Try .of (() -> job == null || job .cancel (mayInterruptIfRunning ))
153
- .recover (ignored -> job != null && job .isCancelled ())
154
- .onSuccess (cancelled -> {
155
- if (cancelled ) {
156
- this .cancelled = tryComplete (Try .failure (new CancellationException ()));
157
- }
158
- });
159
- }
140
+ this .cancelled = tryComplete (Try .failure (new CancellationException ()));
160
141
}
161
142
return this ;
162
143
}
163
144
145
+ private void updateThread () {
146
+ }
147
+
164
148
@ Override
165
- public ExecutorService executorService () {
166
- return executorService ;
149
+ public Executor executor () {
150
+ return executor ;
167
151
}
168
152
169
153
@ Override
@@ -235,7 +219,6 @@ private boolean tryComplete(Try<? extends T> value) {
235
219
actions = this .actions ;
236
220
this .value = Option .some (Try .narrow (value ));
237
221
this .actions = null ;
238
- this .job = null ;
239
222
}
240
223
}
241
224
if (actions != null ) {
@@ -249,9 +232,13 @@ private boolean tryComplete(Try<? extends T> value) {
249
232
250
233
private void perform (Consumer <? super Try <T >> action ) {
251
234
try {
252
- executorService .execute (() -> action .accept (value .get ()));
235
+ executor .execute (() -> action .accept (value .get ()));
253
236
} catch (Throwable x ) {
254
237
// ignored // TODO: tell UncaughtExceptionHandler?
255
238
}
256
239
}
240
+
241
+ private interface Computation <T > {
242
+ void execute (Predicate <Try <? extends T >> tryComplete , Runnable updateThread ) throws Throwable ;
243
+ }
257
244
}
0 commit comments