open Async
open Core
let out = Lazy.force Writer.stdout
let inn = Lazy.force Reader.stdin
let readOrTimeOut =
Deferred.any
[ (after (sec 3.0) >>| fun () -> "Timeout")
; Reader.read_line inn >>| (fun s -> match s with | `Eof -> "Empty" | `Ok str -> str)
]
let run _ =
upon (
let rec loop () =
readOrTimeOut >>=
fun str ->
Writer.write out ("You typed: " ^ str ^ "\n");
Writer.flushed out
>>= fun () -> loop()
in loop () )
(fun _ -> ())
let () =
run ();
never_returns (Scheduler.go ())
My question:
When I run the program, if I let it timeout, it will continuously display “You typed Timeout” as opposed to waiting for a timeout or input every time. Why i this happening?
readOrTimeOut has type string Deferred.t. Once a Deferred.t becomes determined with a value, that value never changes.
In your loop, calling readOrTimeout >>= <function> doesn’t cause a new Deferred.t to be created. It just keeps reading the value out of the same Deferred.t.
You probably want to make readOrTimeout be a function unit -> string Deferred.t instead, so that you can call this function and bind on a new deferred each time through the loop.
Thanks a lot! Now I am facing a different issue.
I get an exception, If I let it timeout, the program throws an exception stating that the reader is already in use. How can I prevent this error? How can I force the Reader,read_line to be “determined” even if the timeout case is hit?
open Async
open Core
let out = Lazy.force Writer.stdout
let inn = Lazy.force Reader.stdin
let stdinPipe = Reader.pipe inn
let readInput () =
Deferred.choose
[ Pipe.read_choice_single_consumer_exn stdinPipe [%here] |> Deferred.Choice.map ~f:Either.first
; Deferred.choice (after (sec 3.0)) (fun _ -> ()) |> Deferred.Choice.map ~f:Either.second
] >>= function
| First data ->
(match data with
| `Eof -> return None
| `Ok data -> return (Some data) )
| Second _ -> return None
let run _ =
upon (
let rec loop () =
readInput () >>=
function
| None -> Writer.write out "You timed out!\n"; Writer.flushed out >>= fun () -> loop()
| Some s -> Writer.write out ("You typed: " ^ s ^ "\n"); Writer.flushed out >>= fun () -> loop()
in loop () )
(fun _ -> ())
let () =
run ();
never_returns (Scheduler.go ())