Timeout Reading From Stdin With Promises using async
Task
Concurrency & Parallelism / Single-Threaded Concurrency / Timeout Reading From Stdin With Promises
Prompt the user to input some text on stdin - if the user does not finish before the timeout, abort.
Opam Packages Used
- async Tested with version: 0.17.0 — Used libraries: async
Code
Async
is Jane Street's concurrent programming library, similar to Lwt
but with
different design choices and better integration with Core
/Base
libraries.
'a Deferred.t
is Async's equivalent to Lwt's promises - it represents a value
that will be available in the future.
open Async
let (let*) = Async.(>>=)
Attempts to read a line from standard input.
Reader.read_line
returns `Ok string when successful, or
`Eof when end-of-file is reached.
Note: Core.Lazy.force
is needed because stdin is initialized lazily
to allow for customization before first use.
let read_name () : string option Deferred.t =
let* s =
Reader.read_line (Core.Lazy.force Reader.stdin)
in
match s with
| `Eof -> Deferred.return (Some "")
| `Ok str -> Deferred.return (Some str)
Async.after
creates a deferred that completes after specified duration
(in this case, 6 seconds).
let timeout () : string option Deferred.t =
let* () = after (Core.sec 6.0) in
Deferred.return None
We create two concurrent operations: reading input and timeout, then use
Deferred.any
to race them against each other, and handle
the result with Async.upon
(similar to .then in JavaScript promises).
let () =
print_endline "Enter your name (don't take too long)";
let race =
Deferred.any [ read_name (); timeout () ]
in
upon race (fun r ->
(match r with
| Some n -> Async_unix.Print.printf "Hello %s\n" n
| None -> Async_unix.Print.print_endline "Too slow!");
The explicit Async.exit
is needed because the Async event-loop
(Scheduler.go
) never returns.
ignore (Async.exit 0));
Core.never_returns (Scheduler.go ())
Discussion
Async is
part of Jane Street's set of libraries and depends on Base
and Core
.
If you are already using Core
you may well prefer Async
over Lwt
for its better "fit".
Note: this example could be improved by adding error handling and/or handling of properly closing stdin in case of timeout.