Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling simultaneous duplicate events in Clojure

I'm trying to handle duplicate events (MIDI note-on and note-off signals coming in triplicate). It seems like using agents and locking works, unless the events happen (nearly) simultaneously.

Here's an example:

(def test-val (agent 0))
(def allow-update (agent true))

(defn increase-val []
  (locking allow-update
    (when @allow-update 
      (send allow-update (fn [_ x] x) false)
      (send test-val + 1)))
  (print @test-val))

(defn run-futures [delay-time]
  (send allow-update  (fn [_ x] x) true)
  (send test-val * 0)
  (dotimes [_ 20] 
    (Thread/sleep delay-time)
    (future (increase-val))))

If I test it with a slight delay between calls to increase-val:

(run-futures 2)
;outputs 0111111111111111111 every time, as expected

But if I let all the calls to increase-val happen all at once:

(run-futures 0)
;001222222222222222
(run-futures 0)
;000000145555555555
(run-futures 0)
;000000013677777777

It seems like the lock doesn't have time to get turned on, so the agent gets increased by multiple futures.

I'm hoping I'm missing something here that will allow me to make sure I don't act on duplicate simultaneous events.

Thanks!

like image 695
crimper Avatar asked Dec 18 '25 20:12

crimper


1 Answers

Because Agents are asynchronous and uncoordinated, there can be a delay between when you send them a message and the actual running of the action that was sent. During this delay it's possible for most, or all, of the calls to (send test-val + 1) to make it through the locked section before the first one actually runs and sets @allow-update to false. You can see this in the leading 0s before the state of test-val gets changed.

atoms may be better suited to interacting with locks, though refs may be the right tool for coordinated access to multiple identities.

like image 146
Arthur Ulfeldt Avatar answered Dec 21 '25 17:12

Arthur Ulfeldt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!