diff options
| author | Ben Culkin <scorpress@gmail.com> | 2023-06-25 16:30:36 -0400 |
|---|---|---|
| committer | Ben Culkin <scorpress@gmail.com> | 2023-06-25 16:30:36 -0400 |
| commit | b8bbd1b015d59523cf2054a6ad42be11dedc8652 (patch) | |
| tree | 2f4fa5f12909961a98d5740122a692e7ef758144 | |
| parent | 69a769bc6474d71f5108af0698dd5454319e2a6c (diff) | |
Add timeout support
Add support for timeouts to Terminal, so you can say you only want to
wait so long for a given reply
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/StreamTerminal.java | 27 | ||||
| -rw-r--r-- | base/src/main/java/bjc/utils/cli/Terminal.java | 38 |
2 files changed, 63 insertions, 2 deletions
diff --git a/base/src/main/java/bjc/utils/cli/StreamTerminal.java b/base/src/main/java/bjc/utils/cli/StreamTerminal.java index 69be8d7..87370f8 100644 --- a/base/src/main/java/bjc/utils/cli/StreamTerminal.java +++ b/base/src/main/java/bjc/utils/cli/StreamTerminal.java @@ -7,6 +7,8 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.locks.*; +import bjc.data.Either; + /** * Implementation of {@link Terminal} using {@link Reader} and {@link Writer} * @@ -149,6 +151,24 @@ public class StreamTerminal implements Terminal, Runnable { return pendingReplies.get(id); } } + + @Override + public Optional<String> awaitReply(long id, TimeUnit unit, long delay) throws InterruptedException { + if (pendingReplies.containsKey(id)) + return Optional.of(pendingReplies.get(id)); + while (true) { + replyLock.lock(); + boolean stat = replyCondition.await(delay, unit); + replyLock.unlock(); + + // If we timed out, say so + if (stat == false) return Optional.empty(); + // Explanation: Since the reply map is add-only, the lock isn't actually + // protecting anything. We just want to wait until a response is received. + if (pendingReplies.containsKey(id)) + return Optional.of(pendingReplies.get(id)); + } + } @Override public Optional<String> checkReply(long id) { @@ -160,5 +180,10 @@ public class StreamTerminal implements Terminal, Runnable { return awaitReply(submitRequest(req)); } - // TODO add variants of the two blocking methods above with timeout support + @Override + public Either<String, Long> submitRequestSync(String req, TimeUnit unit, long delay) throws InterruptedException { + long id = submitRequest(req); + Optional<String> rep = awaitReply(id, unit, delay); + return rep.isEmpty() ? Either.right(id) : Either.left(rep.get()); + } }
\ No newline at end of file diff --git a/base/src/main/java/bjc/utils/cli/Terminal.java b/base/src/main/java/bjc/utils/cli/Terminal.java index a10d82e..e8b3029 100644 --- a/base/src/main/java/bjc/utils/cli/Terminal.java +++ b/base/src/main/java/bjc/utils/cli/Terminal.java @@ -1,6 +1,9 @@ package bjc.utils.cli; import java.util.*; +import java.util.concurrent.TimeUnit; + +import bjc.data.Either; /** * A terminal with support for asking multiple questions, and retrieving the @@ -17,6 +20,7 @@ public interface Terminal { * Submit a request to the terminal * * @param req The body of the request + * * @return The ID of the request */ long submitRequest(String req); @@ -26,15 +30,32 @@ public interface Terminal { * response is available. * * @param id The ID of the request + * * @return The response to that request + * * @throws InterruptedException If we are interrupted waiting for the reply */ String awaitReply(long id) throws InterruptedException; + + /** + * Await a reply for a given request. Will block the current thread until a + * response is available or the specified timeout occurs. + * + * @param id The ID of the request + * @param unit The unit of time to wait + * @param delay The amount of units to wait before timing out + * + * @return The response to that request, or an empty optional if it timed out + * + * @throws InterruptedException If we are interrupted waiting for the reply + */ + Optional<String> awaitReply(long id, TimeUnit unit, long delay) throws InterruptedException; /** * Check if a reply for a request is available, without blocking. * * @param id The ID of the request + * * @return The reply to the request if one is available, and empty otherwise */ Optional<String> checkReply(long id); @@ -47,5 +68,20 @@ public interface Terminal { * @return The reply to the request * @throws InterruptedException If we are interrupted waiting for the reply */ - String submitRequestSync(String req) throws InterruptedException;; + String submitRequestSync(String req) throws InterruptedException; + + /** + * Submit a request and await the reply to it. Will block the current thread + * until a response is received or the timeout occurs. + * + * @param req The request to submit + * @param unit The unit of time to wait + * @param delay The amount of units to wait before timing out + * + * @return The reply to the request, or the ID of the request if the timeout occurred + * + * @throws InterruptedException If we are interrupted waiting for the reply + */ + Either<String, Long> submitRequestSync(String req, TimeUnit unit, long delay) throws InterruptedException; + }
\ No newline at end of file |
