@@ -58,10 +58,15 @@ to IOC if not available. If AOT compiling, go blocks are always compiled
58
58
as normal Clojure code to be run on vthreads and will throw at runtime
59
59
if vthreads are not available (Java <21)
60
60
61
- \" avoid\" - means that vthreads will not be used - you can use this to
62
- minimize impacts if you are not yet ready to evaluate vthreads in your app.
63
- If AOT compiling, go blocks will use IOC. At runtime, io-thread and the
64
- :io thread pool use platform threads
61
+ \" avoid\" - means that vthreads will not be used by core.async - you can
62
+ use this to minimize impacts if you are not yet ready to utilize vthreads
63
+ in your app. If AOT compiling, go blocks will use IOC. At runtime, io-thread
64
+ and the :io thread pool use platform threads
65
+
66
+ Note: existing IOC compiled go blocks from older core.async versions continue
67
+ to work (we retain and load the IOC state machine runtime - this does not
68
+ require the analyzer), and you can interact with the same channels from both
69
+ IOC and vthread code.
65
70
"
66
71
(:refer-clojure :exclude [reduce transduce into merge map take partition
67
72
partition-by bounded-count])
@@ -80,8 +85,8 @@ If AOT compiling, go blocks will use IOC. At runtime, io-thread and the
80
85
81
86
(alias 'core 'clojure.core)
82
87
83
- (when (not (or (dispatch/aot- vthreads? ) ( dispatch/runtime-vthreads? )) )
84
- ( require 'clojure.core.async.impl.go ))
88
+ (def go-becomes-ioc? (not (or (dispatch/vthreads-available-and-allowed? )
89
+ ( dispatch/target-vthreads? )) ))
85
90
86
91
(set! *warn-on-reflection* false )
87
92
@@ -163,11 +168,13 @@ If AOT compiling, go blocks will use IOC. At runtime, io-thread and the
163
168
(timers/timeout msecs))
164
169
165
170
(defmacro defparkingop
171
+ " Emits either parking op or reimplement as blocking op when vthreads
172
+ available."
166
173
[op doc arglist & body]
167
174
(let [as (mapv #(list 'quote %) arglist)
168
175
blockingop (-> op name (str " !" ) symbol)]
169
176
`(def ~(with-meta op {:arglists `(list ~as) :doc doc})
170
- (if (dispatch/runtime- vthreads? )
177
+ (if (dispatch/vthreads-available-and-allowed ? )
171
178
(fn [~'& ~'args]
172
179
~(list* apply blockingop '[args]))
173
180
(fn ~arglist
@@ -198,8 +205,9 @@ If AOT compiling, go blocks will use IOC. At runtime, io-thread and the
198
205
(deref p))))
199
206
200
207
(defparkingop <!
201
- " takes a val from port. Must be called inside a (go ...) block. Will
202
- return nil if closed. Will park if nothing is available."
208
+ " takes a val from port. Must be called inside a (go ...) block, or on
209
+ a virtual thread. Will return nil if closed. Will park if nothing is
210
+ available."
203
211
[port]
204
212
(assert nil " <! used not in (go ...) block" ))
205
213
@@ -238,7 +246,8 @@ If AOT compiling, go blocks will use IOC. At runtime, io-thread and the
238
246
239
247
(defparkingop >!
240
248
" puts a val into port. nil values are not allowed. Must be called
241
- inside a (go ...) block. Will park if no buffer space is available.
249
+ inside a (go ...) block, or on a virtual thread. Will park if no buffer
250
+ space is available.
242
251
Returns true unless port is already closed."
243
252
[port val]
244
253
(assert nil " >! used not in (go ...) block" ))
@@ -381,9 +390,9 @@ If AOT compiling, go blocks will use IOC. At runtime, io-thread and the
381
390
382
391
(defparkingop alts!
383
392
" Completes at most one of several channel operations. Must be called
384
- inside a (go ...) block. ports is a vector of channel endpoints,
385
- which can be either a channel to take from or a vector of
386
- [channel-to-put-to val-to-put], in any combination. Takes will be
393
+ inside a (go ...) block, or on a virtual thread . ports is a vector of
394
+ channel endpoints, which can be either a channel to take from or a vector
395
+ of [channel-to-put-to val-to-put], in any combination. Takes will be
387
396
made as if by <!, and puts will be made as if by >!. Unless
388
397
the :priority option is true, if more than one port operation is
389
398
ready a non-deterministic choice will be made. If no operation is
@@ -522,10 +531,13 @@ If AOT compiling, go blocks will use IOC. At runtime, io-thread and the
522
531
Returns a channel which will receive the result of the body when
523
532
completed"
524
533
[& body]
525
- (cond (dispatch/aot-vthreads? ) `(do (dispatch/ensure-runtime-vthreads! )
526
- (thread-call (^:once fn* [] ~@body) :io ))
527
- (dispatch/runtime-vthreads? ) `(thread-call (^:once fn* [] ~@body) :io )
528
- :default ((find-var 'clojure.core.async.impl.go/go-impl) &env body)))
534
+ (let [rt-check-step (when clojure.core/*compile-files*
535
+ '(dispatch/ensure-runtime-vthreads!))]
536
+ (if go-becomes-ioc?
537
+ (do (dispatch/dynamic-require 'clojure.core.async.impl.go)
538
+ ((find-var 'clojure.core.async.impl.go/go-impl) &env body))
539
+ `(do ~rt-check-step
540
+ (thread-call (^:once fn* [] ~@body) :io )))))
529
541
530
542
(defonce ^:private thread-macro-executor nil )
531
543
0 commit comments