Skip to content

Commit

Permalink
Avoid eval for graalvm
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude authored and niwinz committed Mar 9, 2023
1 parent 230f131 commit 18fea52
Showing 1 changed file with 59 additions and 53 deletions.
112 changes: 59 additions & 53 deletions src/promesa/exec.cljc
Expand Up @@ -60,14 +60,23 @@

(def virtual-threads-available?
"Var that indicates the availability of virtual threads."
#?(:clj (and (pu/has-method? Thread "ofVirtual")
(try
(eval '(Thread/ofVirtual))
true
(catch Throwable cause
false)))
#?(:clj (if (and (pu/has-method? Thread "ofVirtual")
;; the following should succeed with the `--enable-preview` java argument:
;; eval happens on top level = compile time, which is ok for GraalVM
(try (eval '(Thread/ofVirtual))
(catch Exception _ false)))
true
false)
:cljs false))

#?(:clj
(do
(defmacro compile-if-virtual [then else]
(if virtual-threads-available?
then else))
(defmacro compile-when-virtual [body]
`(compile-if-virtual ~body nil))))

;; DEPRECATED
(def ^{:deprecated true
:doc "backward compatibility alias for `virtual-threads-available?`"}
Expand Down Expand Up @@ -111,19 +120,19 @@
^{:doc "A global, thread per task executor service."
:no-doc true}
default-thread-executor
#?(:clj (if virtual-threads-available?
(delay (eval '(java.util.concurrent.Executors/newThreadPerTaskExecutor
^ThreadFactory (promesa.exec/thread-factory))))
default-cached-executor)
#?(:clj (compile-if-virtual
(delay (java.util.concurrent.Executors/newThreadPerTaskExecutor
^ThreadFactory (promesa.exec/thread-factory)))
default-cached-executor)
:cljs default-executor))

(defonce
^{:doc "A global, virtual thread per task executor service."
:no-doc true}
default-vthread-executor
#?(:clj (if virtual-threads-available?
(delay (eval '(java.util.concurrent.Executors/newVirtualThreadPerTaskExecutor)))
default-cached-executor)
#?(:clj (compile-if-virtual
(delay (java.util.concurrent.Executors/newVirtualThreadPerTaskExecutor))
default-cached-executor)
:cljs default-executor))

(defn executor?
Expand Down Expand Up @@ -519,20 +528,18 @@
(->Scheduler)))

#?(:clj
(when virtual-threads-available?
(eval
'(defn thread-per-task-executor
[& {:keys [factory]}]
(let [factory (or (some-> factory resolve-thread-factory)
(thread-factory :name "promesa/thread-per-task/%s"))]
(Executors/newThreadPerTaskExecutor ^ThreadFactory factory))))))
(compile-when-virtual
(defn thread-per-task-executor
[& {:keys [factory]}]
(let [factory (or (some-> factory resolve-thread-factory)
(thread-factory :name "promesa/thread-per-task/%s"))]
(Executors/newThreadPerTaskExecutor ^ThreadFactory factory)))))

#?(:clj
(when virtual-threads-available?
(eval
'(defn vthread-per-task-executor
[]
(Executors/newVirtualThreadPerTaskExecutor)))))
(compile-when-virtual
(defn vthread-per-task-executor
[]
(Executors/newVirtualThreadPerTaskExecutor))))

#?(:clj
(defn forkjoin-executor
Expand Down Expand Up @@ -686,34 +693,33 @@
(pmap #(apply f %) (step-fn (cons coll colls)))))))

#?(:clj
(if virtual-threads-available?
(eval
'(defn fn->thread
[f & {:keys [daemon virtual start priority name]
:or {daemon true virtual false start true priority Thread/NORM_PRIORITY}}]
(let [name (or name (format "promesa/unpooled-thread/%s" (get-next)))
thread (if virtual
(let [thb (Thread/ofVirtual)
thb (.name thb ^String name)]
(.unstarted thb ^Runnable f))
(let [thb (Thread/ofPlatform)
thb (.name thb ^String name)
thb (.priority thb (int priority))
thb (.daemon thb (boolean daemon))]
(.unstarted thb ^Runnable f)))]
(if start
(.start ^Thread thread))
thread)))
(defn fn->thread
[f & {:keys [daemon start priority name]
:or {daemon true start true priority Thread/NORM_PRIORITY}}]
(let [thread (doto (Thread. ^Runnable f)
(.setName ^String name)
(.setPriority (int priority))
(.setDaemon (boolean daemon)))]
(if start
(.start ^Thread thread))
thread))))
(compile-if-virtual
(defn fn->thread
[f & {:keys [daemon virtual start priority name]
:or {daemon true virtual false start true priority Thread/NORM_PRIORITY}}]
(let [name (or name (format "promesa/unpooled-thread/%s" (get-next)))
thread (if virtual
(let [thb (Thread/ofVirtual)
thb (.name thb ^String name)]
(.unstarted thb ^Runnable f))
(let [thb (Thread/ofPlatform)
thb (.name thb ^String name)
thb (.priority thb (int priority))
thb (.daemon thb (boolean daemon))]
(.unstarted thb ^Runnable f)))]
(if start
(.start ^Thread thread))
thread))
(defn fn->thread
[f & {:keys [daemon start priority name]
:or {daemon true start true priority Thread/NORM_PRIORITY}}]
(let [thread (doto (Thread. ^Runnable f)
(.setName ^String name)
(.setPriority (int priority))
(.setDaemon (boolean daemon)))]
(if start
(.start ^Thread thread))
thread))))

#?(:clj
(defmacro thread
Expand Down

0 comments on commit 18fea52

Please sign in to comment.