Skip to content

Commit be295c6

Browse files
committed
Implement CompletionStage whenComplete
1 parent 0ebabc2 commit be295c6

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

src/manifold/deferred.clj

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@
7171
then-handle then-handle-async
7272
then-exceptionally
7373

74-
to-completable-future)
74+
to-completable-future
75+
76+
when-complete when-complete-async)
7577

7678
;; The potemkin abstract type for
7779
;; implementations such as CompletionStage
@@ -158,7 +160,14 @@
158160
(then-exceptionally this operator))
159161

160162
(toCompletableFuture [this]
161-
(to-completable-future this)))
163+
(to-completable-future this))
164+
165+
(whenComplete [this operator]
166+
(when-complete this operator))
167+
(whenCompleteAsync [this operator]
168+
(when-complete-async this operator))
169+
(whenCompleteAsync [this operator executor]
170+
(when-complete-async this operator executor)))
162171

163172
(definline realized?
164173
"Returns true if the manifold deferred is realized."
@@ -1638,8 +1647,16 @@
16381647
#(.complete result %)
16391648
#(.completeExceptionally result %))
16401649

1641-
result
1642-
))
1650+
result))
1651+
1652+
(defn- when-complete [this ^java.util.function.BiConsumer operator]
1653+
(assert-some operator)
1654+
(on-realized this
1655+
#(.accept operator % nil)
1656+
#(.accept operator nil %))
1657+
this)
1658+
1659+
(def ^:private when-complete-async (async-for when-complete))
16431660

16441661
;;;
16451662

test/manifold/deferred_stage_test.clj

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,60 @@
479479
(is (.isDone target))
480480

481481
(is (thrown? RuntimeException (.getNow target nil))))))
482+
483+
484+
485+
(def when-complete-methods
486+
[(fn [^CompletionStage this operator _]
487+
(.whenComplete this operator))
488+
(fn [^CompletionStage this operator _]
489+
(.whenCompleteAsync this operator))
490+
(fn [^CompletionStage this operator executor]
491+
(.whenCompleteAsync this operator executor))])
492+
493+
(defn- test-when-complete-success [method executor]
494+
495+
(let [was-called (atom false)
496+
497+
d1 (d/success-deferred 1)
498+
d2 (method
499+
d1
500+
(fn->BiConsumer
501+
(fn [x t]
502+
(is (= 1 x))
503+
(is (nil? t))
504+
(reset! was-called true)))
505+
executor)]
506+
507+
(is (= @d1 1))
508+
(is (= @d2 1))
509+
(is (= true @was-called))))
510+
511+
(defn- test-when-complete-error [method executor]
512+
513+
(let [was-called (atom false)
514+
515+
d1 (d/error-deferred (RuntimeException.))
516+
d2 (method
517+
d1
518+
(fn->BiConsumer
519+
(fn [x t]
520+
(is (nil? x))
521+
(is (some? t))
522+
(reset! was-called true)))
523+
executor)]
524+
525+
(is (thrown? RuntimeException @d1))
526+
(is (thrown? RuntimeException @d2))
527+
(is (= true @was-called))))
528+
529+
(deftest test-when-complete
530+
531+
(let [executor (Executors/newSingleThreadExecutor)]
532+
(testing "when complete success"
533+
(dorun (for [method when-complete-methods]
534+
(test-when-complete-success method executor))))
535+
536+
(testing "when complete error"
537+
(dorun (for [method when-complete-methods]
538+
(test-when-complete-error method executor))))))

0 commit comments

Comments
 (0)