diff --git a/_02_.Writing-programs.sz b/_02_.Writing-programs.sz index ffb9fff..39bce26 100644 --- a/_02_.Writing-programs.sz +++ b/_02_.Writing-programs.sz @@ -955,7 +955,7 @@ Functions that may suspend execution—whether waiting on a channel, sleeping, o @codeblock[#:lang "bjolang"]|{ (: think (-bjo-> int int)) (defbjo (think n) - (sync (timeout 50)) ;; wait 50 ms, without holding up a thread + (sync (timeout (milliseconds 50))) ;; wait 50 ms, without holding up a thread (* n n)) }| @@ -1035,29 +1035,31 @@ Crucially, calling @code{(chan-recv seat)} does not perform the receive immediat |---------------------------+-------------------------------------------------------------| | @code{(chan-recv ch)} | Receives a value from channel @code{ch} | | @code{(chan-send ch v)} | Sends @code{v} on channel @code{ch} | -| @code{(timeout ms)} | Fires after @code{ms} milliseconds | +| @code{(timeout d)} | Fires after the @code{Duration} @code{d} | | @code{(choose e1 e2 ...)} | Fires when the first of the supplied events occurs | | @code{(wrap e f)} | Fires when @code{e} occurs, applying @code{f} to its value | } +A @code{Duration} is a length of time, made with @code{milliseconds}, @code{seconds}, @code{minutes} or @code{hours}: @code{(timeout (seconds 5))}. It has its unit in its type, so a timer cannot be given a bare number, and one too long for its range raises rather than wrapping round. + With these combinators, deadlines and timeouts become simple functions that compose over any event. For instance, we can enforce a response timeout on our card players: @codeblock[#:lang "bjolang"]|{ -(: within (-> int (Event %a) (Event (Option %a)))) -(defun (within ms ev) +(: within (-> Duration (Event %a) (Event (Option %a)))) +(defun (within d ev) (choose (wrap ev #(Some &)) - (wrap (timeout ms) (fun (u) None)))) + (wrap (timeout d) (fun (u) None)))) (: slow-player (-bjo-> (Chan string) void)) (defbjo (slow-player seat) - (sync (timeout 200)) + (sync (timeout (milliseconds 200))) (sync (chan-send seat "7♣"))) (defbjo (main) (def seat (make-chan)) (spawn (slow-player seat)) - (println (sync (within 50 (chan-recv seat)))) ;; None - (println (sync (within 500 (chan-recv seat)))) ;; (Some 7♣) + (println (sync (within (milliseconds 50) (chan-recv seat)))) ;; None + (println (sync (within (milliseconds 500) (chan-recv seat)))) ;; (Some 7♣) 0) }| @@ -1097,14 +1099,14 @@ The top-level @code{main} function acts as an implicit root scope, which is why |---------------------------------------+------------------------------------------------------------| | @code{(with-scope body ...)} | Waits for child fibers and finalizes open file ports | | @code{(with-cancel (cancel) body ...)} | Binds a @code{cancel} procedure to signal child fibers | -| @code{(with-deadline ms body ...)} | Cancels the scope automatically after @code{ms} ms | +| @code{(with-deadline d body ...)} | Cancels the scope automatically after the duration @code{d} | | @code{(with-shield body ...)} | Shields cleanup operations from parent cancellation | } @codeblock[#:lang "bjolang"]|{ (: fetch (-bjo-> string void)) (defbjo (fetch name) - (sync (timeout 30)) + (sync (timeout (milliseconds 30))) (println #"fetched ${name}")) (: count-up (-bjo-> (Chan int) void)) @@ -1115,7 +1117,7 @@ The top-level @code{main} function acts as an implicit root scope, which is why (defbjo (main) ;; Both are fetched when this returns, or the deadline raises. - (with-deadline 1000 + (with-deadline (seconds 1) (spawn (fetch "a")) (spawn (fetch "b"))) (println "both done") @@ -1249,7 +1251,7 @@ If a transaction raises an exception, it writes nothing, and @code{atomically} r @codeblock[#:lang "bjolang"]|{ ;; A card from the pile, or None after 100 ms. (sync (choose (wrap (atomically-evt (fun (tx) (take-top tx pile))) Some) - (wrap (timeout 100) (fun (_) None)))) + (wrap (timeout (milliseconds 100)) (fun (_) None)))) }| Inside a transaction, @code{(tx-or-else tx a b)} runs @code{a}, and if @code{a} retries, undoes its writes and runs @code{b}. If both retry, the whole transaction waits for a change to anything either of them read.