Skip to content

Commit

Permalink
io-thread impl for pre-vthread release
Browse files Browse the repository at this point in the history
  • Loading branch information
fogus committed Jan 22, 2025
1 parent 3dd3141 commit e2dcf01
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 12 deletions.
20 changes: 8 additions & 12 deletions src/main/clojure/clojure/core/async.clj
Original file line number Diff line number Diff line change
Expand Up @@ -465,28 +465,24 @@ to catch and handle."
(defonce ^:private ^Executor thread-macro-executor
(Executors/newCachedThreadPool (conc/counted-thread-factory "async-thread-macro-%d" true)))

(def ^ExecutorService io-thread-exec
(if (= "21" (System/getProperty "java.vm.specification.version"))
(eval '(Executors/newThreadPerTaskExecutor (-> (Thread/ofVirtual)
(java.lang.Thread$Builder/.name "io-thread-" 0)
.factory)))
thread-macro-executor))
(defonce ^:private ^ExecutorService io-thread-exec thread-macro-executor)

(defmacro io-thread
"Asynchronously executes the body in a virtual thread, returning immediately
to the calling thread.
"Asynchronously executes the body in a thread compatible with I/O workload,
returning immediately to the calling thread. Only blocking operations should
be used in io-thread bodies.
io-thread blocks should not (either directly or indirectly) perform operations
that may block indefinitely. Doing so risks pinning the virtual thread
to its carrier thread.
that never block and run pure compute operations. Parking ops
(i.e. <!, >! and alt!/alts!) used in io-thread bodies will throw at
runtime.
Returns a channel which will receive the result of the body when
completed"
[& body]
`(let [c# (chan 1)
captured-bindings# (Var/getThreadBindingFrame)]
(.execute
io-thread-exec
(.execute ^ExecutorService @#'io-thread-exec
(^:once fn* []
(Var/resetThreadBindingFrame captured-bindings#)
(try
Expand Down
9 changes: 9 additions & 0 deletions src/test/clojure/clojure/core/async_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@
(binding [test-dyn true]
(is (<!! (thread test-dyn))))))

(deftest io-thread-tests
(testing "io-thread"
(let [c1 (chan)
c2 (chan)
c3 (chan)]
(io-thread (>!! c2 (clojure.string/upper-case (<!! c1))))
(io-thread (>!! c3 (clojure.string/reverse (<!! c2))))
(>!! c1 "loop")
(is (= "POOL" (<!! c3))))))

(deftest ops-tests
(testing "map<"
Expand Down

0 comments on commit e2dcf01

Please sign in to comment.