2015-09-16 11 views

Trả lời

4

Có, điều này là an toàn, nhưng có báo trước rằng @Cirdec đã đề cập.

Đối conreteness, hãy xem xét ví dụ sau đó tạo ra một mạng lưới sự kiện bằng cách sử dụng addHandler trong một thread riêng biệt và sau đó gọi fire lặp đi lặp lại trong các chủ đề chính

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() 

(Xem tài liệu "Terminating the program" in Control.Concurrent cho lý do tại sao tôi đã đưa . vòng lặp sự kiện trong các chủ đề chính như trái ngược với đặt mạng trong thread chính)

trong này và tương tự như tình huống, sau đây sẽ tổ chức:

  • Tác vụ IO được thực hiện bởi reactimate sẽ được chạy trong chuỗi gọi fire, không trong chuỗi nơi mạng được biên dịch. Đây là những gì @Cirdec đã đề cập.
  • Nếu có chuỗi thứ hai cũng gọi số fire, thì có thể có khả năng xen kẽ với các cuộc gọi khác đến fire, tức là chương trình có thể gọi đồng thời fire hai lần. Sau đó,
    • Quả chuối phản ứng sử dụng khóa để đảm bảo rằng Hành vi và Sự kiện được cập nhật nhất quán. Bạn có thể coi chúng là các hàm thuần túy Time -> a và liệt kê [(Time,a)] như bình thường.
    • Tuy nhiên, hành động IO từ reactimate s có thể xen kẽ. Nói cách khác, phần FRP tinh khiết sẽ giữ nguyên, nhưng IO thực tế là đối tượng đồng thời như bình thường.
+0

Điều đó làm cho nó rất rõ ràng. –

3

Bắn chính bộ xử lý fire là an toàn; nó đọc một số IORef đang được cập nhật một cách nguyên tử và chạy từng bộ điều khiển được thêm vào trong chuỗi hiện tại. Có hay không đó là an toàn sẽ phụ thuộc vào những gì xử lý đã được thêm vào addHandler.

Sử dụng addHandler trong interpretAsHandler, fromAddHandler hoặc fromChanges phải an toàn. Không có gì tôi biết trong phản ứng chuối có bất kỳ mối quan hệ sợi, và ngay cả khi nó đã làm, đây là những gì newAddHandler đã được thực hiện cho, vì vậy nó nên được an toàn anyway.

Điều bạn cần cẩn thận là các hành động IO() được thực hiện bởi reactimate. Nếu bạn cần phản ứng IO các hành động cần được chạy trong một chuỗi cụ thể (đối với đầu ra OpenGL, v.v.), bạn chỉ cần tạo các hành động IO() sẽ gửi dữ liệu của họ đến chuỗi đó. Trong complete OpenGL example for reactive-banana hành động IO() cho đầu ra OpenGL này, có ái lực luồng, được chạy trong chuỗi OpenGL. Thay vì reactimate ing các Event (IO()) thực hiện trực tiếp chúng được thêm vào một 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 

Các IORef nắm giữ mà IO() hành động để chạy được đọc và mỗi người trong số tất cả các hành động được chạy trong một bối cảnh mà tôi biết là trong OpenGL chủ đề.

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) 
Các vấn đề liên quan