Chez concurrency pt.1: real OS-thread futures + blocking promises (shared heap)
future/future-call run the body on a native thread (fork-thread) over the SAME heap — JVM semantics, not Janet's isolated-heap snapshot. deref blocks on a mutex+condition latch; timed (deref f ms val) uses an absolute deadline. promise is a real blocking promise (deref parks until deliver), replacing the Janet non-blocking atom shim. future?/future-done?/future-cancelled?/future-cancel /realized? are native (the overlay versions read Janet map keys); re-asserted in post-prelude over the overlay. pmap/pcalls/pvalues (overlay, over future) light up for free. Thread-safety this forces: - atoms get a per-atom mutex; swap!/swap-vals! are a JVM-style CAS loop (f runs outside the lock, so a watch/validator can deref the same atom); reset!/ compare-and-set! are atomic. - the dynamic binding stack becomes a Chez thread-parameter, so each future/thread has its own; Chez inherits it at fork, giving binding conveyance (the shim also installs an explicit snapshot). - Thread/sleep really sleeps now (a worker sleeping doesn't block the parent). Re-minted the seed: future-call now resolves at compile time, so pmap compiles to a var-deref instead of the host-static-call fallback that crashed. image.ss unchanged. Corpus: the 2 snapshot cases now match the JVM (shared) not Janet (isolated) — allowlisted on both Chez gates; the two racy future-cancel cases allowlisted; "promise undelivered" (blocks on JVM/Chez, profile :bucket :timeout) skipped like :throws. Zero-Janet corpus 2544 -> 2569, 0 new divergences, floor raised. Full Janet gate + JVM cert green. jolt-byjr
This commit is contained in:
parent
a23095b502
commit
ec30c9e405
10 changed files with 330 additions and 42 deletions
|
|
@ -47,7 +47,28 @@
|
|||
["(map eval [(quote (+ 1 1)) (quote (* 3 3))])" "(2 9)"]
|
||||
["(defmacro add1 [x] (list (quote +) x 1)) (add1 10)" "11"]
|
||||
["(defmacro twice [x] `(do ~x ~x)) (twice (+ 2 3))" "5"]
|
||||
["(defmacro m [x] `(+ ~x 1)) (m (m (m 0)))" "3"]])
|
||||
["(defmacro m [x] `(+ ~x 1)) (m (m (m 0)))" "3"]
|
||||
# jolt-byjr: concurrency — futures/pmap/promise on real OS threads (shared heap).
|
||||
["(deref (future (+ 1 2)))" "3"]
|
||||
["@(future (* 6 7))" "42"]
|
||||
["(deref (future (mapv inc [1 2 3])))" "[2 3 4]"]
|
||||
["(let [f (future (+ 1 1))] [(deref f) (deref f)])" "[2 2]"]
|
||||
["(future? (future 1))" "true"]
|
||||
["(future? 42)" "false"]
|
||||
["(let [f (future 1)] (deref f) (future-done? f))" "true"]
|
||||
["(let [f (future 1)] (deref f) (realized? f))" "true"]
|
||||
["(let [f (future 42)] (deref f) (deref f 1000 :nope))" "42"]
|
||||
["(vec (pmap inc [1 2 3]))" "[2 3 4]"]
|
||||
["(vec (pmap + [1 2 3] [4 5 6]))" "[5 7 9]"]
|
||||
["(vec (pcalls (fn [] 1) (fn [] 2)))" "[1 2]"]
|
||||
["(vec (pvalues (+ 1 2) (+ 3 4)))" "[3 7]"]
|
||||
# shared heap = JVM semantics (NOT Janet's isolated-heap snapshot): a captured
|
||||
# atom is shared, so the future's swap! is visible to the parent.
|
||||
["(let [a (atom 0)] (deref (future (swap! a inc))) @a)" "1"]
|
||||
["(let [a (atom 0)] (dorun (pmap (fn [_] (swap! a inc)) [1 2 3 4])) @a)" "4"]
|
||||
# promise blocks until delivered (JVM), unlike the Janet atom-shim.
|
||||
["(let [p (promise)] (deliver p 7) @p)" "7"]
|
||||
["(let [p (promise)] (future (deliver p :hi)) @p)" ":hi"]])
|
||||
|
||||
(each [src want] cases
|
||||
(def [code out err] (joltc src))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue