2015-09-16 8 views
6

यहप्रतिक्रियाशील-केला में, क्या हैंडलर क्रियाओं को एकाधिक धागे से ट्रिगर करना सुरक्षित है?

(addHandler, fire) <- newAddHandler 

में आग कार्रवाई एक अलग धागे से है जहाँ से प्रतिक्रियाशील-केला ग्राफ संकलित किया गया था को गति प्रदान करने के लिए सुरक्षित है?

उत्तर

4

हां, यह सुरक्षित है, लेकिन @Cirdec का उल्लेख है कि चेतावनी है।

conreteness के लिए, निम्न उदाहरण है कि एक अलग थ्रेड में addHandler उपयोग करके एक ईवेंट नेटवर्क बनाता है पर विचार करें और उसके बाद मुख्य थ्रेड

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 कॉल बार-बार (कारण है कि मैं डाल दिया है के लिए दस्तावेज़ "Terminating the program" in Control.Concurrent देखें । मुख्य थ्रेड के रूप में मुख्य थ्रेड में नेटवर्क डालने के लिए विरोध में घटना पाश)

इस और इसी तरह की परिस्थितियों में, निम्नलिखित का आयोजन करेगा:

  • reactimate द्वारा निष्पादित आईओ क्रियाएं उस थ्रेड में चलेंगी जो fire, पर थ्रेड में नेटवर्क को संकलित किया गया था। @Cirdec पहले से ही यही उल्लेख किया है।
  • यदि कोई दूसरा थ्रेड भी fire पर कॉल कर रहा था, तो यह fire पर अन्य कॉल के साथ संभावित रूप से अंतःस्थापित हो सकता है, यानी कार्यक्रम दो बार समसामयिक रूप से fire पर कॉल कर सकता है। फिर,
    • प्रतिक्रियाशील-केला यह सुनिश्चित करने के लिए एक ताला का उपयोग करता है कि व्यवहार और घटनाक्रम लगातार अद्यतन होते हैं। आप उन्हें शुद्ध कार्यों Time -> a के रूप में देख सकते हैं और सामान्य रूप से [(Time,a)] सूचीबद्ध कर सकते हैं।
    • हालांकि, reactimate एस से IO क्रियाएं interleave हो सकती हैं। दूसरे शब्दों में, शुद्ध एफआरपी हिस्सा शुद्ध रहेगा, लेकिन वास्तविक आईओ सामान्य रूप से समरूपता के अधीन है।
+0

इससे यह बहुत स्पष्ट हो जाता है। –

3

fire फायरिंग हैंडलर स्वयं सुरक्षित है; यह IORef पढ़ता है जिसे परमाणु रूप से अपडेट किया जा रहा है और वर्तमान थ्रेड में जोड़े गए हैंडलरों में से प्रत्येक को चलाता है। चाहे वह सुरक्षित है या नहीं, इस पर निर्भर करेगा कि addHandler में कौन से हैंडलर जोड़े गए हैं।

addHandlerinterpretAsHandler, fromAddHandler, या fromChanges में सुरक्षित होना चाहिए। प्रतिक्रियाशील-केले में मुझे कुछ भी पता नहीं है, इसमें कोई थ्रेड एफ़िनिटी है, और यहां तक ​​कि अगर ऐसा होता है, तो ये newAddHandler के लिए बनाया गया था, इसलिए यह सुरक्षित होना चाहिए।

reactimate द्वारा निष्पादित IO() क्रियाओं के बारे में आपको सावधान रहने की आवश्यकता है। यदि आपको IO क्रियाओं को एक विशिष्ट थ्रेड (ओपनजीएल आउटपुट, आदि के लिए) में चलाने की आवश्यकता है, तो आपको केवल IO() क्रियाएं उत्पन्न करने की आवश्यकता है जो उनके डेटा को उस थ्रेड पर भेज देंगे। इस complete OpenGL example for reactive-bananaIO() ओपनजीएल आउटपुट के लिए क्रियाएं, जिनमें थ्रेड एफ़िनिटी है, ओपनजीएल थ्रेड में चलाए जाते हैं। इसके बजाय reactimateEvent (IO()) ing उन्हें सीधे वे जुड़ जाते हैं क्रियान्वित एक 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 

IORef धारण करने के लिए जो चलाने के लिए IO() कार्यों पढ़ा जाता है और सभी कार्यों में से प्रत्येक एक संदर्भ में चलाए जा रहे हैं कि मैं जानता हूँ कि ओपन में है धागा।

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) 
संबंधित मुद्दे