@@ -17,11 +17,11 @@ go block threads - use Thread.setDefaultUncaughtExceptionHandler()
1717to catch and handle.
1818
1919Use the Java system property `clojure.core.async.executor-factory`
20- to specify a function that will provide ExecutorServices for
20+ to specify a function that will provide Executor for
2121application-wide use by core.async in lieu of its defaults. The
2222property value should name a fully qualified var. The function
2323will be passed a keyword indicating the context of use of the
24- executor, and should return either an ExecutorService , or nil to
24+ executor, and should return either an Executor , or nil to
2525use the default. Results per keyword will be cached and used for
2626the remainder of the application. Possible context arguments are:
2727
@@ -36,37 +36,45 @@ flow/process
3636
3737:core-async-dispatch - used for completion fn handling (e.g. in put!
3838and take!, as well as go block IOC thunk processing) throughout
39- core.async. If not supplied the ExecutorService for :io will be
39+ core.async. If not supplied the Executor for :io will be
4040used instead.
4141
4242The set of contexts may grow in the future so the function should
43- return nil for unexpected contexts.
43+ return nil for unexpected contexts. In the case where system
44+ properties are set to enable the use of virtual threads (see below)
45+ core.async will ignore the cutom executor for :io workloads and
46+ instead use its default Executor to construct virtual threads for
47+ :io. When this circumstance occurs a warning will be printed.
4448
4549Use the Java system property `clojure.core.async.vthreads` to control
4650how core.async uses JDK 21+ virtual threads. The property can be one of
4751the following values:
4852
49- unset - core.async will opportunistically use vthreads when available
50- (≥ Java 21) and will otherwise use the old IOC impl. io-thread and :io
51- thread pool will run on platform threads if vthreads are not available.
52- If AOT compiling, go blocks will always use IOC so that the resulting
53- bytecode works on all JVMs (so no change in compiled output)
53+ unset - means that vthreads will not be used by core.async. If AOT
54+ compiling, go blocks will use IOC. At runtime, io-thread and the :io
55+ thread pool use platform threads.
5456
5557\" target\" - means that you are targeting virtual threads. At runtime
56- from source, go blocks will throw if vthreads are not available.
57- If AOT compiling, go blocks are always compiled as normal Clojure
58- code to be run on vthreads and will throw at runtime if vthreads are
59- not available (Java <21)
60-
61- \" avoid\" - means that vthreads will not be used by core.async - you can
62- use this to minimize impacts if you are not yet ready to utilize vthreads
63- in your app. If AOT compiling, go blocks will use IOC. At runtime, io-thread
64- and the :io thread pool use platform threads
65-
66- Note: existing IOC compiled go blocks from older core.async versions continue
67- to work (we retain and load the IOC state machine runtime - this does not
68- require the analyzer), and you can interact with the same channels from both
69- IOC and vthread code.
58+ from source, go blocks will throw if vthreads are not available. If AOT
59+ compiling, go blocks are always compiled as normal Clojure code to be run
60+ on vthreads and will throw at runtime if vthreads are not available
61+ (Java <21). Further, a second system property setting is required to allow
62+ virtual threads to operate in the way that IOC threads have historically.
63+ The jdk.trackAllThreads property must be set to false to disable JDK global
64+ thread tracking. Without this setting, unterminated virtual threads are
65+ strongly held by the JDK and not garbage-collected when the objects that
66+ they're blocked on are themselves garbage-collected. This condition leads to a
67+ memory leak in the common use case in core.async where go blocks are started
68+ but fall out of scope. Historically, the resources associated with the go block
69+ were collected, but when backed by strongly-held virtual threads they are not.
70+ There are caveats in setting the jdk.trackAllThreads property to false and it's
71+ advised to understand the implications of doing so and the tradeoffs involved
72+ compared to using virtual threads.
73+
74+ Note: Even when targetting virtual threads, existing IOC compiled go blocks
75+ from older core.async versions continue to work (we retain and load the IOC state
76+ machine runtime - this does not require the analyzer), and you can interact with
77+ the same channels from both IOC and vthread code.
7078"
7179 (:refer-clojure :exclude [reduce transduce into merge map take partition
7280 partition-by bounded-count])
0 commit comments