Skip to content

Instantly share code, notes, and snippets.

@RutledgePaulV
Last active February 24, 2021 07:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RutledgePaulV/b858726b919326a6c98f100d1751e799 to your computer and use it in GitHub Desktop.
Save RutledgePaulV/b858726b919326a6c98f100d1751e799 to your computer and use it in GitHub Desktop.
doseq but with work broken out into thread pools of specified sizes
(defmacro workseq [bindings & body]
(let [bind (first (partition 2 bindings))]
(if (empty? bindings)
`(do ~@body nil)
`(let [right# ~(second bind)
value# (first right#)
workers# (second right#)
num-values# (count value#)]
(if (and (< 1 workers#) (< 1 num-values#))
(let [thread-pool# (Executors/newFixedThreadPool workers#)
latch# (CountDownLatch. num-values#)]
(doseq [x# value#]
(let [~(first bind)
x#
thunk#
(bound-fn*
(^:once fn* []
(try
(workseq ~(vec (drop 2 bindings)) ~@body)
(finally
(.countDown latch#)))))]
(.submit ^ThreadPoolExecutor thread-pool# ^Runnable thunk#)))
(.await latch#)
(.shutdownNow thread-pool#)
nil)
(doseq [x# value#]
(let [~(first bind) x#]
(workseq ~(vec (drop 2 bindings)) ~@body))))))))
(comment
(workseq [x [(range 200) 12]]
(locking *out*
(println x))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment