Skip to content

Commit fdbd7f8

Browse files
authored
Merge pull request #210 from arnaudgeiser/master
Add new-thread-fn parameter to manifold.executor/thread-factory
2 parents f08f0a2 + 497c21f commit fdbd7f8

File tree

2 files changed

+64
-15
lines changed

2 files changed

+64
-15
lines changed

src/manifold/executor.clj

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,46 @@
3232
(finally
3333
(.set executor-thread-local executor#)))))
3434

35+
(defn- ^Thread new-thread
36+
"Creates a new `java.lang.Thread`.
37+
38+
It represents the default implementation on `thread-factory` when the
39+
`new-thread-fn` argument is not passed.
40+
41+
Some libraries require a different implementation of a `java.lang.Thread`.
42+
That's the case of Netty which behaves differently when
43+
running on a `io.netty.util.concurrent.FastThreadLocalThread`."
44+
[group target name stack-size]
45+
(Thread. group target name stack-size))
46+
3547
(defn ^ThreadFactory thread-factory
48+
"Returns a `java.util.concurrent.ThreadFactory`.
49+
50+
|:---|:----
51+
| `name-generator` | a zero-argument function, which, when invoked returns the name of the `java.lang.Thread` that will be created. |
52+
| `executor-promise` | a promise eventually containing a `java.util.concurrent.Executor` that will be stored on `manifold.executor/executor-thread-local`. |
53+
| `stack-size` | the desired stack size for the new thread, or nil/zero to indicate that this parameter is to be ignored. |
54+
| `daemon?` | marks the created threads as either daemon or user threads. The Java Virtual Machine exits when the only threads running are all daemon threads. |
55+
| `new-thread-fn` | a four arguments function which returns an implementation of `java.lang.Thread` when called. |"
3656
([name-generator executor-promise]
37-
(thread-factory name-generator executor-promise nil true))
57+
(thread-factory name-generator executor-promise nil true nil))
3858
([name-generator executor-promise stack-size]
39-
(thread-factory name-generator executor-promise stack-size true))
59+
(thread-factory name-generator executor-promise stack-size true nil))
4060
([name-generator executor-promise stack-size daemon?]
41-
(reify ThreadFactory
42-
(newThread [_ runnable]
43-
(let [name (name-generator)
44-
curr-loader (.getClassLoader (class thread-factory))
45-
f #(do
46-
(.set executor-thread-local @executor-promise)
47-
(.run ^Runnable runnable))]
48-
(doto
49-
(if stack-size
50-
(Thread. nil f name stack-size)
51-
(Thread. nil f name))
52-
(.setDaemon daemon?)
53-
(.setContextClassLoader curr-loader)))))))
61+
(thread-factory name-generator executor-promise stack-size daemon? nil))
62+
([name-generator executor-promise stack-size daemon? new-thread-fn]
63+
(let [new-thread (or new-thread-fn new-thread)]
64+
(reify ThreadFactory
65+
(newThread [_ runnable]
66+
(let [name (name-generator)
67+
curr-loader (.getClassLoader (class thread-factory))
68+
f #(do
69+
(.set executor-thread-local @executor-promise)
70+
(.run ^Runnable runnable))
71+
thread ^Thread (new-thread nil f name (or stack-size 0))]
72+
(doto thread
73+
(.setDaemon daemon?)
74+
(.setContextClassLoader curr-loader))))))))
5475

5576
;;;
5677

test/manifold/executor_test.clj

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,31 @@
4040
(let [l (clojure.lang.RT/baseLoader)]
4141
(deliver in-thread-loader l))))
4242
(is (instance? clojure.lang.DynamicClassLoader @in-thread-loader))))
43+
44+
(defn- ^ThreadFactory thread-factory
45+
([] (thread-factory nil))
46+
([new-thread-fn] (thread-factory new-thread-fn nil))
47+
([new-thread-fn stack-size]
48+
(let [num-threads (atom 0)
49+
tf (e/thread-factory
50+
#(str "my-pool-prefix" (swap! num-threads inc))
51+
(deliver (promise) nil)
52+
stack-size
53+
false
54+
new-thread-fn)]
55+
tf)))
56+
57+
(deftest test-thread-factory
58+
(let [tf (thread-factory)]
59+
(is (.newThread tf (constantly nil))))
60+
(let [tf (thread-factory
61+
(fn [group target _ stack-size]
62+
(Thread. group target "custom-name" stack-size)))
63+
thread (.newThread tf (constantly nil))]
64+
(is (= "custom-name" (.getName thread))))
65+
(let [tf (thread-factory
66+
(fn [group target _ stack-size]
67+
(Thread. group target "custom-name" stack-size))
68+
500)
69+
thread (.newThread tf (constantly nil))]
70+
(is (= "custom-name" (.getName thread)))))

0 commit comments

Comments
 (0)