2015-09-16 5 views

答えて

4

はい、これは安全ですが、@ 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は通常どおり並行処理が行われます。
+0

これは非常に明確です。 –

3

fireハンドラ自体の起動は安全です。原子的に更新されているIORefを読み取り、現在のスレッドで追加された各ハンドラを実行します。それが安全であるかどうかは、ハンドラがaddHandlerに追加されたかどうかによって決まります。

fromAddHandler、またはfromChangesaddHandlerを使用すると安全です。私が知っているのは反応性のバナナには何のスレッド類似性もなく、たとえそれがあったとしても、これは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) 
関連する問題