Thread/CountDownLatch + SoftReference/ConcurrentHashMap so core.cache fully passes
Closes the last clojure.core.cache gaps (now 1314/0/0, including the 1000-thread cache-stampede): - java.lang.Thread over Chez fork-thread (shared heap): (Thread. thunk) + start/ join/run/isAlive, on a "user-thread" tag distinct from Thread/currentThread's interrupt shim. java.util.concurrent.CountDownLatch (count/mutex/condition). - java.util.concurrent.ConcurrentHashMap = the mutable HashMap shim; get / count / contains? read it (clojure.core), which SoftCache uses on its backing map. - java.lang.ref.SoftReference / ReferenceQueue: no JVM GC reference semantics, so the referent is held strongly (a SoftCache is unbounded rather than GC-evicting), but enqueue / poll work so clear-soft-cache! drains the queue. JVM-certified corpus rows. make test + shakesmoke green.
This commit is contained in:
parent
5d0989a860
commit
9312ad0937
3 changed files with 98 additions and 0 deletions
|
|
@ -328,3 +328,47 @@
|
|||
(def-var! "jolt.host" "interrupt!" jolt-interrupt!)
|
||||
(def-var! "jolt.host" "interrupted?" jolt-interrupted?)
|
||||
(def-var! "jolt.host" "run-interruptible" jolt-run-interruptible)
|
||||
|
||||
;; --- java.lang.Thread / java.util.concurrent.CountDownLatch -----------------
|
||||
;; Real OS threads over Chez fork-thread (shared heap — a captured atom/var is
|
||||
;; shared). A Thread runs its Runnable thunk; start forks, join waits on a
|
||||
;; condition latched at completion. CountDownLatch is a counting barrier.
|
||||
(define (make-jthread thunk) (make-jhost "user-thread" (vector thunk #f (make-mutex) (make-condition))))
|
||||
(for-each (lambda (nm) (register-class-ctor! nm (lambda (thunk . _) (make-jthread thunk))))
|
||||
'("Thread" "java.lang.Thread"))
|
||||
(register-host-methods! "user-thread"
|
||||
(list (cons "start" (lambda (self)
|
||||
(let ((st (jhost-state self)) (snap (dyn-binding-stack)))
|
||||
(fork-thread (lambda ()
|
||||
(dyn-binding-stack snap)
|
||||
(guard (e (#t #f)) (jolt-invoke (vector-ref st 0)))
|
||||
(with-mutex (vector-ref st 2)
|
||||
(vector-set! st 1 #t)
|
||||
(condition-broadcast (vector-ref st 3)))))
|
||||
jolt-nil)))
|
||||
(cons "run" (lambda (self) (jolt-invoke (vector-ref (jhost-state self) 0)) jolt-nil))
|
||||
(cons "join" (lambda (self . _)
|
||||
(let ((st (jhost-state self)))
|
||||
(with-mutex (vector-ref st 2)
|
||||
(let loop () (unless (vector-ref st 1) (condition-wait (vector-ref st 3) (vector-ref st 2)) (loop)))))
|
||||
jolt-nil))
|
||||
(cons "isAlive" (lambda (self) (not (vector-ref (jhost-state self) 1))))
|
||||
(cons "interrupt" (lambda (self . _) jolt-nil))
|
||||
(cons "setDaemon" (lambda (self . _) jolt-nil))))
|
||||
|
||||
(define (make-jlatch n) (make-jhost "count-down-latch" (vector n (make-mutex) (make-condition))))
|
||||
(for-each (lambda (nm) (register-class-ctor! nm (lambda (n . _) (make-jlatch (jnum->exact n)))))
|
||||
'("CountDownLatch" "java.util.concurrent.CountDownLatch"))
|
||||
(register-host-methods! "count-down-latch"
|
||||
(list (cons "countDown" (lambda (self)
|
||||
(let ((st (jhost-state self)))
|
||||
(with-mutex (vector-ref st 1)
|
||||
(when (> (vector-ref st 0) 0) (vector-set! st 0 (- (vector-ref st 0) 1)))
|
||||
(when (= (vector-ref st 0) 0) (condition-broadcast (vector-ref st 2)))))
|
||||
jolt-nil))
|
||||
(cons "await" (lambda (self . _)
|
||||
(let ((st (jhost-state self)))
|
||||
(with-mutex (vector-ref st 1)
|
||||
(let loop () (when (> (vector-ref st 0) 0) (condition-wait (vector-ref st 2) (vector-ref st 1)) (loop)))))
|
||||
jolt-nil))
|
||||
(cons "getCount" (lambda (self) (vector-ref (jhost-state self) 0)))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue