sodium 0.7.0.0 → 0.8.0.0
raw patch · 5 files changed
+82/−6 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- FRP.Sodium.Context: ioReactive :: Context r => IO a -> Reactive r a
+ FRP.Sodium.Context: class Context r => ContextIO r
+ FRP.Sodium.Context: executeAsyncIO :: ContextIO r => Event r (IO a) -> Event r a
+ FRP.Sodium.Context: executeSyncIO :: ContextIO r => Event r (IO a) -> Event r a
+ FRP.Sodium.IO: executeAsyncIO :: Event Plain (IO a) -> Event Plain a
+ FRP.Sodium.IO: executeSyncIO :: Event Plain (IO a) -> Event Plain a
+ FRP.Sodium.Internal: data Plain
+ FRP.Sodium.Internal: dep :: a -> Dep
+ FRP.Sodium.Internal: unsafeNewIORef :: a -> b -> IORef a
Files
- sodium.cabal +8/−2
- src/FRP/Sodium/Context.hs +22/−2
- src/FRP/Sodium/IO.hs +48/−0
- src/FRP/Sodium/Internal.hs +4/−1
- src/FRP/Sodium/Plain.hs +0/−1
sodium.cabal view
@@ -1,5 +1,5 @@ name: sodium-version: 0.7.0.0+version: 0.8.0.0 synopsis: Sodium Reactive Programming (FRP) System description: A general purpose Reactive Programming (FRP) system. This is part of a project to@@ -41,6 +41,8 @@ * 0.6.0.2 - Fix memory leak - see memory-test-8 & memory-test-8a; . * 0.7.0.0 - Add split primitive.+ .+ * 0.8.0.0 - Add executeIO primitive. license: BSD3 license-file: LICENSE@@ -145,8 +147,12 @@ library hs-source-dirs: src- exposed-modules: FRP.Sodium, FRP.Sodium.Internal, FRP.Sodium.Context+ exposed-modules: FRP.Sodium,+ FRP.Sodium.Internal,+ FRP.Sodium.Context,+ FRP.Sodium.IO other-modules: FRP.Sodium.Plain build-depends: base >= 4.3.0.0 && < 4.8.0.0, containers >= 0.4.0.0 && < 0.6.0.0, mtl >= 2.0.0.0 && < 2.2.0.0+ ghc-options: -O2
src/FRP/Sodium/Context.hs view
@@ -26,8 +26,6 @@ -- -- State changes to 'hold' values occur after processing of the transaction is complete. sync :: Reactive r a -> IO a- -- Lift an arbitrary IO action into a 'Reactive'.- ioReactive :: IO a -> Reactive r a -- | Returns an event, and a push action for pushing a value into the event. newEvent :: Reactive r (Event r a, a -> Reactive r ()) -- | Listen for firings of this event. The returned @IO ()@ is an IO action@@ -88,6 +86,28 @@ -- a block of input data into frames. We obviously want each frame to have -- its own transaction so that state is updated separately each frame. split :: Event r [a] -> Event r a++class Context r => ContextIO r where+ -- | Execute the specified IO operation asynchronously on a separate thread, and+ -- signal the output event in a new transaction upon its completion.+ --+ -- Caveat: Where 'switch' or 'switchE' is used, when some reactive logic has been+ -- switched away, we rely on garbage collection to actually disconnect this logic+ -- from any input it may be listening to. With normal Sodium code, everything is+ -- pure, so before garbage collection happens, the worst we will get is some wasted+ -- CPU cycles. If you are using 'executeAsyncIO'/'executeSyncIO' inside a 'switch'+ -- or 'switchE', however, it is possible that logic that has been switched away+ -- hasn't been garbage collected yet. This logic /could/ still run, and if it has+ -- observable effects, you could see it running after it is supposed to have been+ -- switched out. One way to avoid this is to pipe the source event for IO out of the+ -- switch, run the 'executeAsyncIO'/'executeSyncIO' outside the switch, and pipe its+ -- output back into the switch contents.+ executeAsyncIO :: Event r (IO a) -> Event r a+ -- | Execute the specified IO operation synchronously and fire the output event+ -- in the same transaction.+ --+ -- Caveat: See 'executeAsyncIO'.+ executeSyncIO :: Event r (IO a) -> Event r a -- | A time-varying value, British spelling. type Behaviour r a = Behavior r a
+ src/FRP/Sodium/IO.hs view
@@ -0,0 +1,48 @@+module FRP.Sodium.IO where++import FRP.Sodium.Context+import FRP.Sodium.Internal++import Control.Concurrent (forkIO)+++-- | Execute the specified IO operation asynchronously on a separate thread, and+-- signal the output event in a new transaction upon its completion.+--+-- Caveat: Where 'switch' or 'switchE' is used, when some reactive logic has been+-- switched away, we rely on garbage collection to actually disconnect this logic+-- from any input it may be listening to. With normal Sodium code, everything is+-- pure, so before garbage collection happens, the worst we will get is some wasted+-- CPU cycles. If you are using 'executeAsyncIO'/'executeSyncIO' inside a 'switch'+-- or 'switchE', however, it is possible that logic that has been switched away+-- hasn't been garbage collected yet. This logic /could/ still run, and if it has+-- observable effects, you could see it running after it is supposed to have been+-- switched out. One way to avoid this is to pipe the source event for IO out of the+-- switch, run the 'executeAsyncIO'/'executeSyncIO' outside the switch, and pipe its+-- output back into the switch contents.+executeAsyncIO :: Event Plain (IO a) -> Event Plain a+executeAsyncIO ev = Event gl cacheRef (dep ev)+ where+ cacheRef = unsafeNewIORef Nothing ev+ gl = do+ (l, push, nodeRef) <- ioReactive newEventImpl+ unlistener <- later $ linkedListen ev (Just nodeRef) False $ \action -> do+ ioReactive $ do+ _ <- forkIO $ sync . push =<< action+ return ()+ addCleanup_Listen unlistener l++-- | Execute the specified IO operation synchronously and fire the output event+-- in the same transaction.+--+-- Caveat: See 'executeAsyncIO'.+executeSyncIO :: Event Plain (IO a) -> Event Plain a+executeSyncIO ev = Event gl cacheRef (dep ev)+ where+ cacheRef = unsafeNewIORef Nothing ev+ gl = do+ (l, push, nodeRef) <- ioReactive newEventImpl+ unlistener <- later $ linkedListen ev (Just nodeRef) False $ \action -> do+ push =<< ioReactive action+ addCleanup_Listen unlistener l+
src/FRP/Sodium/Internal.hs view
@@ -19,7 +19,10 @@ addCleanup_Listen, Sample(..), addCleanup_Sample,- later+ later,+ dep,+ unsafeNewIORef,+ Plain ) where import qualified FRP.Sodium.Context as C
src/FRP/Sodium/Plain.hs view
@@ -110,7 +110,6 @@ } sync = sync- ioReactive = ioReactive newEvent = newEvent listen = listen never = never