Timers take a Duration
timeout and with-deadline take a Duration, made with milliseconds, seconds, minutes or hours; within takes one too. 🤖 Generated with [ECA](https://eca.dev) (anthropic/claude-opus-5-5) Co-Authored-By: eca-agent <git@eca.dev>
This commit is contained in:
parent
3f8c13cc2f
commit
cefa2313ad
1 changed files with 14 additions and 12 deletions
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue