Skip to content

Commit 86f8365

Browse files
committed
io-thread with dynamic vthread use through the runtime ExecutorService
1 parent 313569a commit 86f8365

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

src/main/clojure/clojure/core/async.clj

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ to catch and handle."
3333
)
3434
(:import [java.util.concurrent.atomic AtomicLong]
3535
[java.util.concurrent.locks Lock]
36-
[java.util.concurrent Executors Executor ThreadLocalRandom]
36+
[java.util.concurrent Executors Executor ThreadLocalRandom ExecutorService]
3737
[java.util Arrays ArrayList]
38-
[clojure.lang Var]))
38+
[clojure.lang Var]
39+
[java.lang Thread$Builder]))
3940

4041
(alias 'core 'clojure.core)
4142

@@ -465,6 +466,37 @@ to catch and handle."
465466
(defonce ^:private ^Executor thread-macro-executor
466467
(Executors/newCachedThreadPool (conc/counted-thread-factory "async-thread-macro-%d" true)))
467468

469+
(def ^ExecutorService io-thread-exec
470+
(if (= "21" (System/getProperty "java.vm.specification.version"))
471+
(eval '(Executors/newThreadPerTaskExecutor (-> (Thread/ofVirtual)
472+
(Thread$Builder/.name "io-thread-" 0)
473+
.factory)))
474+
thread-macro-executor))
475+
476+
(defmacro io-thread
477+
"Asynchronously executes the body in a virtual thread, returning immediately
478+
to the calling thread.
479+
480+
io-thread blocks should not (either directly or indirectly) perform operations
481+
that may block indefinitely. Doing so risks pinning the virtual thread
482+
to its carrier thread.
483+
484+
Returns a channel which will receive the result of the body when
485+
completed"
486+
[& body]
487+
`(let [c# (chan 1)
488+
captured-bindings# (Var/getThreadBindingFrame)]
489+
(.execute
490+
io-thread-exec
491+
(^:once fn* []
492+
(Var/resetThreadBindingFrame captured-bindings#)
493+
(try
494+
(let [result# (do ~@body)]
495+
(>!! c# result#))
496+
(finally
497+
(close! c#)))))
498+
c#))
499+
468500
(defn thread-call
469501
"Executes f in another thread, returning immediately to the calling
470502
thread. Returns a channel which will receive the result of calling

0 commit comments

Comments
 (0)