在reactive-banana中,从多个线程触发处理程序操作是否安全?

mig*_*rao 6 haskell frp reactive-banana

触发火灾动作是否安全

(addHandler, fire) <- newAddHandler
Run Code Online (Sandbox Code Playgroud)

从一个不同的线程,编译反应香蕉图?

Hei*_*mus 4

是的,这是安全的,但有 @Cirdec 提到的警告。

为了具体起见,请考虑以下示例,该示例addHandler在单独的线程中使用创建事件网络,然后fire在主线程中重复调用

import Control.Concurrent (myThreadId, threadDelay, forkIO)

main = do
    ...
    (addHandler, fire) <- newAddHandler

    let networkDescription :: MomentIO ()
        networkDescription = do
           e <- fromAddHandler addHandler
           ...
           reactimate $ (print =<< myThreadId) <$ e   -- reactimate

    forkIO $ do
        network <- compile networkDescription
        actuate network
    ...
    forever $ do                                      -- event loop
        threadDelay (10^6)
        fire ()
Run Code Online (Sandbox Code Playgroud)

(请参阅 Control.Concurrent 中的文档“终止程序”,了解为什么我将事件循环放在主线程中,而不是将网络放在主线程中。)

在这种情况和类似情况下,以下情况将成立:

  • 执行的 IO 操作reactimate将在调用 的线程中运行fire而不是在编译网络的线程中运行。这就是@Cirdec 已经提到的。
  • 如果有第二个线程也在调用fire,那么它可能会与其他对 的调用交错fire,即程序可能会fire同时调用两次。然后,
    • Reactive-banana 使用锁来确保行为和事件的更新一致。您可以像往常一样将它们视为纯函数Time -> a和列表[(Time,a)]
    • 然而,来自 s 的 IO 操作reactimate可能会交错。换句话说,纯 FRP 部分将保持纯粹,但实际 IO 仍会受到并发的影响。