You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The interface may be best described by the formula:
23
-
```
23
+
```java
24
24
Promise==CompletionStage+Future
25
25
```
26
26
@@ -32,7 +32,7 @@ This is why this project was ever started. `CompletableTask` is the implementati
32
32
a. `CompletableTask.asyncOn(Executor executor)`
33
33
34
34
Returns a resolved no-value `Promise` that is “bound” to the specified executor. I.e. any function passed to composition methods of `Promise` (like `thenApplyAsync` / `thenAcceptAsync` / `whenCompleteAsync` etc.) will be executed using this executor unless executor is overridden via explicit composition method parameter. Moreover, any nested composition calls will use same executor, if it’s not redefined via explicit composition method parameter:
35
-
```
35
+
```java
36
36
CompletableTask
37
37
.asyncOn(myExecutor)
38
38
.thenApplyAsync(myValueGenerator)
@@ -44,7 +44,7 @@ All of `myValueGenerator`, `myConsumer`, `myActtion` will be executed using `myE
44
44
b. `CompletableTask.complete(T value, Executor executor)`
45
45
46
46
Same as above, but the starting point is a resolved `Promise` with the specified value:
47
-
```
47
+
```java
48
48
CompletableTask
49
49
.complete("Hello!", myExecutor)
50
50
.thenApplyAsync(myMapper)
@@ -56,7 +56,7 @@ All of `myMapper`, `myTransformer`, `myConsumer`, `myActtion` will be executed u
56
56
57
57
Additionally, you may submit [Supplier](https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html) / [Runnable](https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html) to the [Executor](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html) right away, in a similar way as with [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html):
Most importantly, all composed promises support true cancellation (incl. interrupting thread) for the functions supplied as arguments:
68
-
```
68
+
```java
69
69
Promise<?> p1 =
70
70
CompletableTask
71
71
.asyncOn(myExecutor)
@@ -78,7 +78,77 @@ p1.cancel(true);
78
78
```
79
79
In the example above `myConsumer` will be interrupted if already in progress. Both `p1` and `p2` will be resolved faulty: `p1` with a [CancellationException](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CancellationException.html) and `p2` with a [CompletionException](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionException.html).
80
80
81
-
## 3. Utility class Promises
81
+
## 3. DependentPromise
82
+
As it mentioned above, once you cancel `Promise`, all `Promise`-s that depends on this promise are completed with [CompletionException](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionException.html) wrapping[CancellationException](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CancellationException.html). This is a standard behavior, and [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) works just like this.
83
+
84
+
However, then you cancel derrived `Promise`, the original `Promise` is not cancelled:
85
+
```java
86
+
Promise<?> original =CompletableTask.supplyAsync(() -> someIoBoundMethod(), myExecutor);
So if you cancel `derrived` above it's [Runnable](https://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html) method, wrapping `someMethod`, is interrupted. However `original` promise is not cancelled and `someIoBoundMethod` keeps running. This is not always a desired behavior, consider the following method:
returnCompletableTask.supplyAsync( () -> loadXml(url) ).thenApplyAsync( xml -> parseXml(xml) );
96
+
}
97
+
98
+
...
99
+
Promise<DataStructure> p = loadData("http://someserver.com/rest/ds");
100
+
...
101
+
if (someCondition()) {
102
+
// Only second promise is canceled, parseXml.
103
+
p.cancel(true);
104
+
}
105
+
```
106
+
107
+
Clients of this method see only derrived promise, and once they decide to cancel it, it is expected that any of `loadXml` and `parseXml` will be interrupted if not completed yet. To address this issue the library provides [DependentPromise](https://github.com/vsilaev/tascalate-concurrent/blob/master/src/main/java/net/tascalate/concurrent/DependentPromise.java) class:
Promise<DataStructure> p = loadData("http://someserver.com/rest/ds");
117
+
...
118
+
if (someCondition()) {
119
+
// Now the whole chain is canceled.
120
+
p.cancel(true);
121
+
}
122
+
```
123
+
[DependentPromise](https://github.com/vsilaev/tascalate-concurrent/blob/master/src/main/java/net/tascalate/concurrent/DependentPromise.java) overloads methods like `thenApply` / `thenRun` / `thenAccept` / `thenCombine` etc with additional argument:
124
+
- if method accepts no other [CompletionStage](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html), like `thenApply` / `thenRun` / `thenAccept` etc, then it's a boolean flag `enlistOrigin` to specify whether or not original `Promise` should be enlisted for cancelation.
125
+
- if method accepts other [CompletionStage](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html), like `thenCombine` / `applyToEither` / `thenAcceptBoth` etc, then it's a set of [PromiseOrigin](https://github.com/vsilaev/tascalate-concurrent/blob/master/src/main/java/net/tascalate/concurrent/PromiseOrigin.java) enum values, that specifies whether or not original `Promise` and/or `CompletionStage` supplied as argument should be enlisted for cancelation along with resulting promise, for example:
Please note, then in release 0.5.4 there is a new default method `dependent` in interface [Promise](https://github.com/vsilaev/tascalate-concurrent/blob/master/src/main/java/net/tascalate/concurrent/Promise.java) that serves the same purpose and allows to write chained calls:
It’s not mandatory to use any specific subclasses of `Executor` with `CompletableTask` – you may use any implementation. However, someone may find beneficial to have a `Promise`-aware `ExecutorService` API. Below is a list of related classes/interfaces:
0 commit comments