Support for java.util.concurrent.ForkJoinPool-specific operations such as managed block and task fork/join. Additionally supports concept of 'exception-safe' via wrapping executing code and unwrapper result post execution in order avoid wrapping exceptions and breaking calling code that may be expecting specific exception types.
Some of the api's fall back to regular executor service code when called.
One thing to note is there is no support for bound-fn in this codebase so it is on the user to use bound-fn-like constructs if support for dynamic variables is required in their code.
Example:
(defn split-parallel-reduce
"Perform a parallel reduction of a spliterator using the provided ExecutorService"
[executor-service split ideal-split init-fn rfn merge-fn]
(let [n-elems (proto/estimate-count split)
pool (or executor-service (ForkJoinPool/commonPool))]
(if (or (<= n-elems (long ideal-split)) (= n-elems Long/MAX_VALUE))
(split-reduce rfn (init-fn) split)
(if-let [[lhs rhs] (proto/split split)]
(let [lt (fjp/safe-fork-task pool (split-parallel-reduce pool lhs ideal-split init-fn rfn merge-fn))
rt (fjp/safe-fork-task pool (split-parallel-reduce pool rhs ideal-split init-fn rfn merge-fn))]
(merge-fn (fjp/managed-block-unwrap lt) (fjp/managed-block-unwrap rt)))))))
Support for java.util.concurrent.ForkJoinPool-specific operations such as managed block and task fork/join.
Additionally supports concept of 'exception-safe' via wrapping executing code and unwrapper result post
execution in order avoid wrapping exceptions and breaking calling code that may be expecting specific
exception types.
Some of the api's fall back to regular executor service code when called.
One thing to note is there is no support for bound-fn in this codebase so it is on
the user to use bound-fn-like constructs if support for dynamic variables is required
in their code.
Example:
```clojure
(defn split-parallel-reduce
"Perform a parallel reduction of a spliterator using the provided ExecutorService"
[executor-service split ideal-split init-fn rfn merge-fn]
(let [n-elems (proto/estimate-count split)
pool (or executor-service (ForkJoinPool/commonPool))]
(if (or (<= n-elems (long ideal-split)) (= n-elems Long/MAX_VALUE))
(split-reduce rfn (init-fn) split)
(if-let [[lhs rhs] (proto/split split)]
(let [lt (fjp/safe-fork-task pool (split-parallel-reduce pool lhs ideal-split init-fn rfn merge-fn))
rt (fjp/safe-fork-task pool (split-parallel-reduce pool rhs ideal-split init-fn rfn merge-fn))]
(merge-fn (fjp/managed-block-unwrap lt) (fjp/managed-block-unwrap rt)))))))
```User-bindable cpu pool to allow custom forkjoinpools
User-bindable cpu pool to allow custom forkjoinpools
(common-pool)Returns (ForkJoinPool/commonPool)
Returns (ForkJoinPool/commonPool)
(common-pool-parallelism)Integer parallelism assigned to the common pool
Integer parallelism assigned to the common pool
(cpu-pool)Get the currently bound cpu pool as a forkjoinpool
Get the currently bound cpu pool as a forkjoinpool
(exception-safe & code)Wrap code in an exception-safe wrapper - returns a map with either
:ham-fisted.fjp/result or :ham-fisted.fjp.error.
Wrap code in an exception-safe wrapper - returns a map with either `:ham-fisted.fjp/result` or `:ham-fisted.fjp.error`.
(in-fork-join-pool?)Returns true if this task is executing in a fork join pool thread
Returns true if this task is executing in a fork join pool thread
(make-blocker finished? wait-till-finished)(make-blocker finished? wait-till-finished get-value)Make a ForkJoinPool$ManagedBlocker managed blocker from a set of functions.
finished? - returns truthy if the op has finishedwait-till-finished? - blocks until finished. finished? is checked and wait-till-finished is
called again if finished? returns falsy. This is so that wait-till-finished can be easily
bound to LockSupport/park.get-value - Return the value - this will be called once finished? has returned true.Make a `ForkJoinPool$ManagedBlocker` managed blocker from a set of functions. * `finished?` - returns truthy if the op has finished * `wait-till-finished?` - blocks until finished. finished? is checked and wait-till-finished is called again if finished? returns falsy. This is so that wait-till-finished can be easily bound to LockSupport/park. * `get-value` - Return the value - this will be called once finished? has returned true.
(managed-block dly)(managed-block finished? wait-till-finished get-value)Block on a delay or future using the fjp system's managed blocking facility. Safe to call all the time whether the current system is in a forkjoinpool task or not.
Block on a delay or future using the fjp system's managed blocking facility. Safe to call all the time whether the current system is in a forkjoinpool task or not.
(managed-block-unwrap dly)managed block then safe unwrap the exception-safe result
managed block then safe unwrap the exception-safe result
(on-cp & code)Run arbitrary code on the common-pool. Make sure any blocking operations are wrapped in managed-block.
Run arbitrary code on the common-pool. Make sure any blocking operations are wrapped in [[managed-block]].
(on-cpu-pool & code)Run code on the cpu pool. Code on run the cpu pool must use [managed-block] as opposed to deref
Run code on the cpu pool. Code on run the cpu pool must use [managed-block] as opposed to deref
(safe-fork-task pool & code)Called from within an executing task, fork a executing some code and wrapping it in exception-safe
then calling [[fork-task]]
Called from within an executing task, fork a executing some code and wrapping it in [[exception-safe]] then calling [[fork-task]]
(unwrap-safe m)Unwrap result created via executing code wrapped in exception-safe. Throws original exception if found.
Unwrap result created via executing code wrapped in [[exception-safe]]. Throws original exception if found.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |