Skip to content

Commit

Permalink
simplifying io-thread impl
Browse files Browse the repository at this point in the history
  • Loading branch information
fogus committed Jan 23, 2025
1 parent e477c08 commit c4e1551
Showing 1 changed file with 25 additions and 37 deletions.
62 changes: 25 additions & 37 deletions src/main/clojure/clojure/core/async.clj
Original file line number Diff line number Diff line change
Expand Up @@ -468,49 +468,37 @@ to catch and handle."
(defonce ^:private ^ExecutorService io-thread-exec
(Executors/newCachedThreadPool (conc/counted-thread-factory "io-thread-macro-%d" true)))

(defmacro io-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.
(defn thread-call
"Executes f in another thread, returning immediately to the calling
thread. Returns a channel which will receive the result of calling
f when completed, then close."
([f] (thread-call f thread-macro-executor))
([f ^ExecutorService exec]
(let [c (chan 1)]
(let [binds (Var/getThreadBindingFrame)]
(.execute exec
(fn []
(Var/resetThreadBindingFrame binds)
(try
(let [ret (f)]
(when-not (nil? ret)
(>!! c ret)))
(finally
(close! c))))))
c)))

io-thread bodies should not (either directly or indirectly) perform operations
that never block nor run pure compute operations. Parking ops
(i.e. <!, >! and alt!/alts!) used in io-thread bodies will throw at
(defmacro io-thread
"Asynchronously executes the body in a thread intended for I/O
workloads, returning immediately to the calling thread.
io-thread bodies may (either directly or indirectly) perform
operations that may block indefinitely. 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 ^ExecutorService @#'io-thread-exec
(^:once fn* []
(Var/resetThreadBindingFrame captured-bindings#)
(try
(let [result# (do ~@body)]
(when-not (nil? result#)
(>!! c# result#)))
(finally
(close! c#)))))
c#))

(defn thread-call
"Executes f in another thread, returning immediately to the calling
thread. Returns a channel which will receive the result of calling
f when completed, then close."
[f]
(let [c (chan 1)]
(let [binds (Var/getThreadBindingFrame)]
(.execute thread-macro-executor
(fn []
(Var/resetThreadBindingFrame binds)
(try
(let [ret (f)]
(when-not (nil? ret)
(>!! c ret)))
(finally
(close! c))))))
c))
`(thread-call (^:once fn* [] ~@body) @#'io-thread-exec))

(defmacro thread
"Executes the body in another thread, returning immediately to the
Expand Down

0 comments on commit c4e1551

Please sign in to comment.