|
8 | 8 |
|
9 | 9 | (ns ^{:skip-wiki true} |
10 | 10 | clojure.core.async.impl.dispatch |
11 | | - (:import [java.util.concurrent Executors ExecutorService ThreadFactory])) |
| 11 | + (:import [java.util.concurrent Executors Executor ThreadFactory])) |
12 | 12 |
|
13 | 13 | (set! *warn-on-reflection* true) |
14 | 14 |
|
|
72 | 72 | [workload] |
73 | 73 | (Executors/newCachedThreadPool (counted-thread-factory (str "async-" (name workload) "-%d") true))) |
74 | 74 |
|
| 75 | +(def virtual-threads-available? |
| 76 | + (try |
| 77 | + (Class/forName "java.lang.Thread$Builder$OfVirtual") |
| 78 | + true |
| 79 | + (catch ClassNotFoundException _ |
| 80 | + false))) |
| 81 | + |
| 82 | +(def ^:private virtual-thread? |
| 83 | + (if virtual-threads-available? |
| 84 | + (eval `(fn [^Thread t#] (~'.isVirtual t#))) |
| 85 | + (constantly false))) |
| 86 | + |
| 87 | +(defn in-vthread? [] |
| 88 | + (and virtual-threads-available? |
| 89 | + (virtual-thread? (Thread/currentThread)))) |
| 90 | + |
| 91 | +(defn- make-io-executor |
| 92 | + [] |
| 93 | + (if virtual-threads-available? |
| 94 | + (let [svt (.getDeclaredMethod Thread "startVirtualThread" (into-array Class [Runnable]))] |
| 95 | + (reify Executor |
| 96 | + (execute [_ r] |
| 97 | + (.invoke svt nil (object-array [r]))))) |
| 98 | + (make-ctp-named :io))) |
| 99 | + |
75 | 100 | (defn ^:private create-default-executor |
76 | 101 | [workload] |
77 | 102 | (case workload |
|
80 | 105 | :mixed (make-ctp-named :mixed))) |
81 | 106 |
|
82 | 107 | (def executor-for |
83 | | - "Given a workload tag, returns an ExecutorService instance and memoizes the result. By |
| 108 | + "Given a workload tag, returns an Executor instance and memoizes the result. By |
84 | 109 | default, core.async will defer to a user factory (if provided via sys prop) or construct |
85 | | - a specialized ExecutorService instance for each tag :io, :compute, and :mixed. When |
| 110 | + a specialized Executor instance for each tag :io, :compute, and :mixed. When |
86 | 111 | given the tag :core-async-dispatch it will default to the executor service for :io." |
87 | 112 | (memoize |
88 | | - (fn ^ExecutorService [workload] |
| 113 | + (fn ^Executor [workload] |
89 | 114 | (let [sysprop-factory (when-let [esf (System/getProperty "clojure.core.async.executor-factory")] |
90 | 115 | (requiring-resolve (symbol esf))) |
91 | 116 | sp-exec (and sysprop-factory (sysprop-factory workload))] |
92 | 117 | (or sp-exec |
93 | 118 | (if (= workload :core-async-dispatch) |
94 | | - (executor-for :io) |
| 119 | + (executor-for :mixed) |
95 | 120 | (create-default-executor workload))))))) |
96 | 121 |
|
97 | 122 | (defn exec |
98 | 123 | [^Runnable r workload] |
99 | | - (let [^ExecutorService e (executor-for workload)] |
| 124 | + (let [^Executor e (executor-for workload)] |
100 | 125 | (.execute e r))) |
101 | 126 |
|
102 | 127 | (defn run |
|
0 commit comments