我需要一个函数,当使用特定的输入参数调用时,执行提供的函数 g,但只有在另一个提供的函数 f 使用相同的输入参数完成执行之后。还有一个要求,当使用相同的输入args多次调用该函数时,f仅在第一次调用时执行一次,其他调用等待此完成,然后直接执行g。
编辑:该解决方案应该在不同线程上并行运行时工作,并且还应该有效地使用线程。例如,阻塞应该基于每个输入而不是整个函数。
我对该功能的第一次尝试如下:
(defn dependent-func
([f g]
(let [mem (atom {})]
(fn [& args]
(->> (get (locking mem
(swap! mem (fn [latch-map args]
(if (contains? latch-map args)
latch-map
(let [new-latch (CountDownLatch. 1)
new-latch-map (assoc latch-map args new-latch)]
(->> (Thread. #(do (apply f args)
(.countDown new-latch)))
(.start))
new-latch-map))) args)) args)
(.await))
(apply g args)))))
Run Code Online (Sandbox Code Playgroud)
这似乎满足我的要求,并且等待 f 是基于每个输入的,所以我对此相对满意。最初我希望只使用交换!进行内存更新,但不幸的是交换!明确指出该函数位于 swap! 可以被多次调用(我在测试中看到过这一点)。因此,我最终不得不在更新时锁定内存,这真的很难看。
我确信一定有一种更干净的方法可以比我更好地利用 Closure 的并发机制,但到目前为止我还没有找到它。
任何建议将不胜感激。
谢谢,
马特。