等待原子更改超时

Eug*_*sky 0 clojure

有没有办法做一些(Thread/sleep millis my-atom)如果my-atom在millis之前被改变就会醒来的事情?

或者我必须clojure.core.async使用频道代替手表?

Tay*_*ood 5

您可以使用a执行此操作promise,使用deref超时:

(def p (promise))
(future ;; some other thread starts working with the promise
  (Thread/sleep 500)
  (deliver p :finished-early))
(deref p 1000 :timed-out) ;; => :finished-early
Run Code Online (Sandbox Code Playgroud)

如果睡眠花费的时间超过了1000那么deref就会回来:timed-out.

更新:我现在看到你的问题更具体地说是原子.在这种情况下,您仍然可以通过在原子上添加监视来使用promise,并在值发生更改时传递promise:

(def p (promise))
(def a (atom {}))
(add-watch a :watch-changed
           (fn [_ _ old new]
             (when-not (= old new) (deliver p :changed))))
(future
  (Thread/sleep 1001)
  (swap! a assoc :foo 1))
(deref p 1000 :timed-out) ;; => :changed
Run Code Online (Sandbox Code Playgroud)

或者在可重复使用的函数形式中,r可以是任何IRef类型:

(defn await-change [r timeout-ms]
  (let [p (promise)]
    (try
      (add-watch r :await-change ;; keyword must be unique per ref!
                 (fn [_ _ old new]
                   (when-not (= old new) (deliver p :changed))))
      (deref p timeout-ms :timed-out)
      (finally
        (remove-watch r :await-change)))))

(def a (atom {}))
(future
  (Thread/sleep 500)
  (swap! a assoc :foo 1))
(await-change a 1000) ;; => :changed
Run Code Online (Sandbox Code Playgroud)