leonoel / missionary

A functional effect and streaming system for Clojure/Script
Eclipse Public License 2.0
620 stars 25 forks source link

multithreaded reactors ? #62

Open leonoel opened 2 years ago

leonoel commented 2 years ago

Current implementation of reactor allows events to be triggered from any thread within a single reactor, with a single lock to ensure propagation turns are serialized. However, this is a dangerous feature because when multiple reactors are involved it is rather easy to deadlock the system, e.g :

(defn echo [in out]
  (m/ap (loop []
          (in nil)
          (m/? (m/via m/cpu))
          (m/amb (m/? out) (recur)))))

(let [l (m/mbx)
      r (m/mbx)]
  (m/join vector
    (m/reactor (m/stream! (echo l r)))
    (m/reactor (m/stream! (echo r l)))))

The only way to solve the deadlock problem is to bind each reactor to an event loop to make sure only one thread is ever able to trigger propagation turns. This raises the question, is there a single valid use case for multithreaded reactors ? If there isn't any, it may be safer to require all events to happen from a single thread within a single reactor, and raise an error otherwise. This would prevent deadlock issues, also removing the lock could slightly improve performance.