erlang: erlang:send_after/3 + cancel_timer/1 + monotonic_time (T1+T2, 766/766)

Logical-clock timer wheel in the scheduler. send_after schedules a
message-delivery event at an absolute deadline (clock + Time ms);
cancel_timer marks a live timer cancelled and reports remaining ms,
or false. Time advances only when the runnable queue drains, jumping
to the earliest pending deadline (deterministic, no wall clock).

monotonic_time/0,1 exposes the logical ms clock.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 17:44:19 +00:00
parent 29e4234b14
commit 3dbb3e318a
6 changed files with 326 additions and 31 deletions

View File

@@ -1147,7 +1147,7 @@
(and (er-atom? ms) (= (get ms :name) "infinity"))
(er-eval-receive-loop node pid env)
(= ms 0) (er-eval-receive-poll node pid env)
:else (er-eval-receive-timed node pid env)))))
:else (er-eval-receive-timed node pid env (+ (er-clock) ms))))))
;; after 0 — poll once; on no match, run the after-body immediately.
(define
@@ -1161,12 +1161,15 @@
(get r :value)
(er-eval-body (get node :after-body) env)))))
;; after Ms — suspend; on resume check :timed-out. When the scheduler
;; runs out of other work it fires one pending timeout per round.
;; after Ms — suspend with an absolute `deadline` (logical ms). On
;; resume check :timed-out: the scheduler fires the earliest pending
;; deadline once the runnable queue drains. A non-matching message can
;; wake the process early; it re-suspends on the SAME deadline so the
;; timeout window is not extended.
(define
er-eval-receive-timed
(fn
(node pid env)
(node pid env deadline)
(let
((r (er-try-receive (get node :clauses) pid env)))
(if
@@ -1174,6 +1177,7 @@
(get r :value)
(do
(er-proc-set! pid :has-timeout true)
(er-proc-set! pid :timeout-deadline deadline)
(call/cc
(fn
(k)
@@ -1186,7 +1190,7 @@
(er-proc-set! pid :timed-out false)
(er-proc-set! pid :has-timeout false)
(er-eval-body (get node :after-body) env))
(er-eval-receive-timed node pid env)))))))
(er-eval-receive-timed node pid env deadline)))))))
;; Scan mailbox in arrival order. For each msg, try every clause.
;; On first match: remove that msg from mailbox and return body value.