は、反応性バナナグラフがコンパイルされた別のスレッドからリアクティブバナナでは、複数のスレッドからハンドラアクションをトリガするのは安全ですか?
(addHandler, fire) <- newAddHandler
で火災アクションをトリガーすることが安全ですか?
は、反応性バナナグラフがコンパイルされた別のスレッドからリアクティブバナナでは、複数のスレッドからハンドラアクションをトリガするのは安全ですか?
(addHandler, fire) <- newAddHandler
で火災アクションをトリガーすることが安全ですか?
はい、これは安全ですが、@ Cirdecが言及した警告があります。 conretenessについては
、別のスレッドでaddHandler
を使用して、イベントのネットワークを作成し、(私が入れた理由のためのマニュアルを参照してください"Terminating the program" in Control.Concurrentメインスレッド
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()
で繰り返しfire
を呼び出して、次の例を考えてみメインスレッドでネットワークを置くこととは対照的に、メインスレッドのイベントループ)これと同様の状況で
は、次のように保持する。
reactimate
によって実行されるIOアクションは、ネットワークがコンパイルされたスレッドでfire
,ではなくでないスレッドで実行されます。これは@ Cirdecがすでに述べたものです。fire
も呼び出している2番目のスレッドがある場合、fire
への他の呼び出しと潜在的にインターリーブする可能性があります。つまり、プログラムはfire
を同時に2回呼び出している可能性があります。次に、
Time -> a
として扱い、いつものように[(Time,a)]
をリストすることができます。reactimate
からのIOアクションはインターリーブされる可能性があります。言い換えれば、純粋なFRP部分は純粋なままですが、実際のIOは通常どおり並行処理が行われます。fire
ハンドラ自体の起動は安全です。原子的に更新されているIORef
を読み取り、現在のスレッドで追加された各ハンドラを実行します。それが安全であるかどうかは、ハンドラがaddHandler
に追加されたかどうかによって決まります。
、fromAddHandler
、またはfromChanges
でaddHandler
を使用すると安全です。私が知っているのは反応性のバナナには何のスレッド類似性もなく、たとえそれがあったとしても、これはnewAddHandler
のものなので、とにかく安全でなければなりません。
あなたが気をつける必要があるのは、reactimate
によって実行されるIO()
アクションです。 IO
特定のスレッド(OpenGL出力など)で実行する必要のあるアクションを反応させる必要がある場合は、そのスレッドにデータを送信するアクションを生成する必要があります。このcomplete OpenGL example for reactive-bananaでは、スレッドアフィニティを持つOpenGL出力のためのアクションは、OpenGLスレッドで実行されます(IO()
)。代わりにreactimate
のそれらを実行Event (IO())
が直接それらが実行するIO()
アクションが読み込まれ、すべてのアクションのそれぞれが、私が知っているコンテキストで実行されているIORef
保持OpenGLであるIORef
whenIdleRef <- newIORef (return())
let
addWhenIdle :: IO() -> IO()
addWhenIdle y = atomicModifyIORef' whenIdleRef (\x -> (x >> y,()))
runWhenIdle :: IO()
runWhenIdle = atomicModifyIORef' whenIdleRef (\x -> (return(), x)) >>= id
let networkDescription :: forall t. Frameworks t => Moment t()
networkDescription = do
reactimate $ fmap addWhenIdle (whenIdle outputs)
^ ^
| Event (IO())
Stuff the event into an IORef
に追加されているINGの糸。
idleCallback $= Just (do -- will be executed in the OpenGL thread when it's idle
getCurrentTime >>= raiseTime
runWhenIdle -- run those `IO()` actions in this thread
postRedisplay Nothing)
これは非常に明確です。 –