From 540f9962a21db4b01aa0692c9f7eb4391fdb7a7a Mon Sep 17 00:00:00 2001 From: Neil C Smith Date: Mon, 9 Dec 2024 15:09:59 +0000 Subject: [PATCH] Add Async bind to link two Async together. --- .../org/praxislive/code/userapi/Async.java | 26 +++++++++++++++++ .../praxislive/code/userapi/AsyncTest.java | 29 +++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/praxiscore-code/src/main/java/org/praxislive/code/userapi/Async.java b/praxiscore-code/src/main/java/org/praxislive/code/userapi/Async.java index 7a50bef..6439a59 100644 --- a/praxiscore-code/src/main/java/org/praxislive/code/userapi/Async.java +++ b/praxiscore-code/src/main/java/org/praxislive/code/userapi/Async.java @@ -159,6 +159,24 @@ private void unlink(Link link) { } } + /** + * Bind a target Async to complete when a source Async completes. When the + * source Async completes, the target will be completed with the same result + * or error. + * + * @param result type + * @param source source async + * @param target target async + */ + public static void bind(Async source, Async target) { + Objects.requireNonNull(target); + if (source.done()) { + complete(source, target); + } else { + source.link(handler(async -> complete(async, target))); + } + } + /** * Create an Async that will complete when the provided async call * completes, by extracting the first call argument and attempting to map to @@ -239,6 +257,14 @@ public static CompletableFuture toCompletableFuture(Async async) { } } + private static void complete(Async source, Async target) { + if (source.failed()) { + target.fail(source.error()); + } else { + target.complete(source.result()); + } + } + private static void completeExtract(Async asyncCall, Async asyncValue, Class type, int argIdx) { try { if (asyncCall.failed()) { diff --git a/praxiscore-code/src/test/java/org/praxislive/code/userapi/AsyncTest.java b/praxiscore-code/src/test/java/org/praxislive/code/userapi/AsyncTest.java index f5d705e..89c49ba 100644 --- a/praxiscore-code/src/test/java/org/praxislive/code/userapi/AsyncTest.java +++ b/praxiscore-code/src/test/java/org/praxislive/code/userapi/AsyncTest.java @@ -49,6 +49,31 @@ public void testError() { assertNull(async.result()); } + @Test + public void testBind() { + Async source = new Async<>(); + Async target = new Async<>(); + Async.bind(source, target); + source.complete("FOO"); + assertTrue(target.done()); + assertEquals("FOO", target.result()); + + source = new Async<>(); + target = new Async<>(); + source.complete("BAR"); + Async.bind(source, target); + assertTrue(target.done()); + assertEquals("BAR", target.result()); + + source = new Async<>(); + target = new Async<>(); + Async.bind(source, target); + PError error = PError.of("ERROR"); + source.fail(error); + assertTrue(target.done()); + assertSame(error, target.error()); + } + @Test public void testExtractArg() { // Test Value extract @@ -144,7 +169,7 @@ public void testToCompletableFuture() { asyncString.fail(PError.of(ex)); assertTrue(futureString.isCompletedExceptionally()); assertSame(ex, futureString.exceptionNow()); - + // error before link asyncString = new Async<>(); ex = new Exception("FOO"); @@ -152,7 +177,7 @@ public void testToCompletableFuture() { futureString = Async.toCompletableFuture(asyncString); assertTrue(futureString.isCompletedExceptionally()); assertSame(ex, futureString.exceptionNow()); - + // test queued and future asyncString = new Async<>(); futureString = Async.toCompletableFuture(asyncString);