@@ -747,6 +747,7 @@ instance GEq SpiderTimelineEnv where
747data EventEnv x
747data EventEnv x
748 = EventEnv { eventEnvAssignments :: !(IORef [SomeAssignment x]) -- Needed for Subscribe
748 = EventEnv { eventEnvAssignments :: !(IORef [SomeAssignment x]) -- Needed for Subscribe
749 , eventEnvHoldInits :: !(IORef [SomeHoldInit x]) -- Needed for Subscribe
749 , eventEnvHoldInits :: !(IORef [SomeHoldInit x]) -- Needed for Subscribe
750+ , eventEnvDynInits :: !(IORef [SomeDynInit x])
750 , eventEnvMergeUpdates :: !(IORef [SomeMergeUpdate x])
751 , eventEnvMergeUpdates :: !(IORef [SomeMergeUpdate x])
751 , eventEnvMergeInits :: !(IORef [SomeMergeInit x]) -- Needed for Subscribe
752 , eventEnvMergeInits :: !(IORef [SomeMergeInit x]) -- Needed for Subscribe
752 , eventEnvClears :: !(IORef [SomeClear]) -- Needed for Subscribe
753 , eventEnvClears :: !(IORef [SomeClear]) -- Needed for Subscribe
@@ -780,6 +781,10 @@ instance HasSpiderTimeline x => Defer (SomeHoldInit x) (EventM x) where
780 {-# INLINE getDeferralQueue #-}
781 {-# INLINE getDeferralQueue #-}
781 getDeferralQueue = asksEventEnv eventEnvHoldInits
782 getDeferralQueue = asksEventEnv eventEnvHoldInits
784+instance HasSpiderTimeline x => Defer (SomeDynInit x) (EventM x) where
785+ {-# INLINE getDeferralQueue #-}
786+ getDeferralQueue = asksEventEnv eventEnvDynInits
783instance Defer (SomeHoldInit x) (BehaviorM x) where
788instance Defer (SomeHoldInit x) (BehaviorM x) where
784 {-# INLINE getDeferralQueue #-}
789 {-# INLINE getDeferralQueue #-}
785 getDeferralQueue = BehaviorM $ asks snd
790 getDeferralQueue = BehaviorM $ asks snd
@@ -952,6 +957,8 @@ data Root x (k :: * -> *)
953data SomeHoldInit x = forall p. Patch p => SomeHoldInit !(Hold x p)
958data SomeHoldInit x = forall p. Patch p => SomeHoldInit !(Hold x p)
960+data SomeDynInit x = forall p. Patch p => SomeDynInit !(Dyn x p)
955data SomeMergeUpdate x = SomeMergeUpdate
962data SomeMergeUpdate x = SomeMergeUpdate
956 { _someMergeUpdate_update :: !(EventM x [EventSubscription x])
963 { _someMergeUpdate_update :: !(EventM x [EventSubscription x])
957 , _someMergeUpdate_invalidateHeight :: !(IO ())
964 , _someMergeUpdate_invalidateHeight :: !(IO ())
@@ -963,14 +970,20 @@ newtype SomeMergeInit x = SomeMergeInit { unSomeMergeInit :: EventM x () }
963-- EventM can do everything BehaviorM can, plus create holds
970-- EventM can do everything BehaviorM can, plus create holds
964newtype EventM x a = EventM { unEventM :: IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadException, MonadAsyncException) -- The environment should be Nothing if we are not in a frame, and Just if we are - in which case it is a list of assignments to be done after the frame is over
971newtype EventM x a = EventM { unEventM :: IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadException, MonadAsyncException) -- The environment should be Nothing if we are not in a frame, and Just if we are - in which case it is a list of assignments to be done after the frame is over
966−newtype ComputeM x a = ComputeM (ReaderT (IORef [SomeHoldInit x]) IO a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
973+newtype ComputeM x a = ComputeM (ReaderT (IORef [SomeHoldInit x], IORef [SomeDynInit x]) IO a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
968instance Defer (SomeHoldInit x) (ComputeM x) where
975instance Defer (SomeHoldInit x) (ComputeM x) where
969− getDeferralQueue = ComputeM ask
976+ getDeferralQueue = ComputeM $ asks fst
978+instance Defer (SomeDynInit x) (ComputeM x) where
979+ getDeferralQueue = ComputeM $ asks snd
971{-# INLINABLE runComputeM #-}
981{-# INLINABLE runComputeM #-}
972−runComputeM :: Defer (SomeHoldInit x) m => ComputeM x a -> m a
982+runComputeM :: (Defer (SomeHoldInit x) m, Defer (SomeDynInit x) m) => ComputeM x a -> m a
973−runComputeM (ComputeM a) = liftIO . runReaderT a =<< getDeferralQueue
983+runComputeM (ComputeM a) = do
984+ holds <- getDeferralQueue
985+ dyns <- getDeferralQueue
986+ liftIO $ runReaderT a (holds, dyns)
975newtype MergeSubscribedParent x a = MergeSubscribedParent { unMergeSubscribedParent :: EventSubscription x }
988newtype MergeSubscribedParent x a = MergeSubscribedParent { unMergeSubscribedParent :: EventSubscription x }
@@ -1103,7 +1116,7 @@ instance HasSpiderTimeline x => Align (Event x) where
1103newtype Dyn x p = Dyn { unDyn :: IORef (Either (BehaviorM x (PatchTarget p), Event x p) (Hold x p)) }
1116newtype Dyn x p = Dyn { unDyn :: IORef (Either (BehaviorM x (PatchTarget p), Event x p) (Hold x p)) }
1105newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
1118newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
1106−newMapDyn f d = dynamicDynIdentity $ unsafeDyn (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
1119+newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
1108--TODO: Avoid the duplication between this and R.zipDynWith
1121--TODO: Avoid the duplication between this and R.zipDynWith
1109zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)
1122zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)
@@ -1119,10 +1132,17 @@ zipDynWith f da db =
1119 return (a, b)
1132 return (a, b)
1120 These (Identity a) (Identity b) -> return (a, b)
1133 These (Identity a) (Identity b) -> return (a, b)
1121 return $ Just $ Identity $ f a b
1134 return $ Just $ Identity $ f a b
1122− in dynamicDynIdentity $ unsafeDyn (f <$> readBehaviorUntracked (dynamicCurrent da) <*> readBehaviorUntracked (dynamicCurrent db)) ec
1135+ in dynamicDynIdentity $ unsafeBuildDynamic (f <$> readBehaviorUntracked (dynamicCurrent da) <*> readBehaviorUntracked (dynamicCurrent db)) ec
1137+buildDynamic :: (Defer (SomeDynInit x) m, Patch p) => BehaviorM x (PatchTarget p) -> Event x p -> m (Dyn x p)
1138+buildDynamic readV0 v' = do
1139+ result <- liftIO $ newIORef $ Left (readV0, v')
1140+ let !d = Dyn result
1141+ defer $ SomeDynInit d
1124−unsafeDyn :: BehaviorM x (PatchTarget p) -> Event x p -> Dyn x p
1144+unsafeBuildDynamic :: BehaviorM x (PatchTarget p) -> Event x p -> Dyn x p
1125−unsafeDyn readV0 v' = Dyn $ unsafeNewIORef x $ Left x
1145+unsafeBuildDynamic readV0 v' = Dyn $ unsafeNewIORef x $ Left x
1126 where x = (readV0, v')
1146 where x = (readV0, v')
1128-- ResultM can read behaviors and events
1148-- ResultM can read behaviors and events
@@ -1796,24 +1816,31 @@ fan e =
1797 in EventSelector $ \k -> eventFan k f
1817 in EventSelector $ \k -> eventFan k f
1799−runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeMergeInit x] -> EventM x ()
1819+runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeDynInit x] -> IORef [SomeMergeInit x] -> EventM x ()
1800−runHoldInits holdInitRef mergeInitRef = do
1820+runHoldInits holdInitRef dynInitRef mergeInitRef = do
1801 holdInits <- liftIO $ readIORef holdInitRef
1821 holdInits <- liftIO $ readIORef holdInitRef
1822+ dynInits <- liftIO $ readIORef dynInitRef
1802 mergeInits <- liftIO $ readIORef mergeInitRef
1823 mergeInits <- liftIO $ readIORef mergeInitRef
1803− unless (null holdInits && null mergeInits) $ do
1824+ unless (null holdInits && null dynInits && null mergeInits) $ do
1804 liftIO $ writeIORef holdInitRef []
1825 liftIO $ writeIORef holdInitRef []
1826+ liftIO $ writeIORef dynInitRef []
1805 liftIO $ writeIORef mergeInitRef []
1827 liftIO $ writeIORef mergeInitRef []
1806 mapM_ initHold holdInits
1828 mapM_ initHold holdInits
1829+ mapM_ initDyn dynInits
1807 mapM_ unSomeMergeInit mergeInits
1830 mapM_ unSomeMergeInit mergeInits
1808− runHoldInits holdInitRef mergeInitRef
1831+ runHoldInits holdInitRef dynInitRef mergeInitRef
1810initHold :: HasSpiderTimeline x => SomeHoldInit x -> EventM x ()
1833initHold :: HasSpiderTimeline x => SomeHoldInit x -> EventM x ()
1811initHold (SomeHoldInit h) = void $ getHoldEventSubscription h
1834initHold (SomeHoldInit h) = void $ getHoldEventSubscription h
1836+initDyn :: HasSpiderTimeline x => SomeDynInit x -> EventM x ()
1837+initDyn (SomeDynInit d) = void $ getDynHold d
1813newEventEnv :: IO (EventEnv x)
1839newEventEnv :: IO (EventEnv x)
1814newEventEnv = do
1840newEventEnv = do
1815 toAssignRef <- newIORef [] -- This should only actually get used when events are firing
1841 toAssignRef <- newIORef [] -- This should only actually get used when events are firing
1816 holdInitRef <- newIORef []
1842 holdInitRef <- newIORef []
1843+ dynInitRef <- newIORef []
1817 mergeUpdateRef <- newIORef []
1844 mergeUpdateRef <- newIORef []
1818 mergeInitRef <- newIORef []
1845 mergeInitRef <- newIORef []
1819 heightRef <- newIORef zeroHeight
1846 heightRef <- newIORef zeroHeight
@@ -1821,12 +1848,13 @@ newEventEnv = do
1821 toClearRootRef <- newIORef []
1848 toClearRootRef <- newIORef []
1822 coincidenceInfosRef <- newIORef []
1849 coincidenceInfosRef <- newIORef []
1823 delayedRef <- newIORef IntMap.empty
1850 delayedRef <- newIORef IntMap.empty
1824− return $ EventEnv toAssignRef holdInitRef mergeUpdateRef mergeInitRef toClearRef toClearRootRef heightRef coincidenceInfosRef delayedRef
1851+ return $ EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeInitRef toClearRef toClearRootRef heightRef coincidenceInfosRef delayedRef
1826clearEventEnv :: EventEnv x -> IO ()
1853clearEventEnv :: EventEnv x -> IO ()
1827−clearEventEnv (EventEnv toAssignRef holdInitRef mergeUpdateRef mergeInitRef toClearRef toClearRootRef heightRef coincidenceInfosRef delayedRef) = do
1854+clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeInitRef toClearRef toClearRootRef heightRef coincidenceInfosRef delayedRef) = do
1828 writeIORef toAssignRef []
1855 writeIORef toAssignRef []
1829 writeIORef holdInitRef []
1856 writeIORef holdInitRef []
1857+ writeIORef dynInitRef []
1830 writeIORef mergeUpdateRef []
1858 writeIORef mergeUpdateRef []
1831 writeIORef mergeInitRef []
1859 writeIORef mergeInitRef []
1832 writeIORef heightRef zeroHeight
1860 writeIORef heightRef zeroHeight
@@ -1841,7 +1869,7 @@ runFrame a = SpiderHost $ ask >>= \_ -> lift $ do
1841 let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
1869 let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
1842 let go = do
1870 let go = do
1843 result <- a
1871 result <- a
1844− runHoldInits (eventEnvHoldInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
1872+ runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
1845 return result
1873 return result
1846 result <- runEventM go
1874 result <- runEventM go
1847 toClear <- readIORef $ eventEnvClears env
1875 toClear <- readIORef $ eventEnvClears env
@@ -1873,7 +1901,7 @@ runFrame a = SpiderHost $ ask >>= \_ -> lift $ do
1873 writeIORef (switchSubscribedBehaviorParents subscribed) []
1901 writeIORef (switchSubscribedBehaviorParents subscribed) []
1874 writeIORef (eventEnvHoldInits env) [] --TODO: Should we reuse this?
1902 writeIORef (eventEnvHoldInits env) [] --TODO: Should we reuse this?
1875 e <- runBehaviorM (readBehaviorTracked (switchSubscribedParent subscribed)) (Just (wi', switchSubscribedBehaviorParents subscribed)) $ eventEnvHoldInits env
1903 e <- runBehaviorM (readBehaviorTracked (switchSubscribedParent subscribed)) (Just (wi', switchSubscribedBehaviorParents subscribed)) $ eventEnvHoldInits env
1876− runEventM $ runHoldInits (eventEnvHoldInits env) (eventEnvMergeInits env) --TODO: Is this actually OK? It seems like it should be, since we know that no events are firing at this point, but it still seems inelegant
1904+ runEventM $ runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) --TODO: Is this actually OK? It seems like it should be, since we know that no events are firing at this point, but it still seems inelegant
1877 --TODO: Make sure we touch the pieces of the SwitchSubscribed at the appropriate times
1905 --TODO: Make sure we touch the pieces of the SwitchSubscribed at the appropriate times
1878 sub <- newSubscriberSwitch subscribed
1906 sub <- newSubscriberSwitch subscribed
1879 subscription <- runReaderT (unSpiderHost (runFrame ({-# SCC "subscribeSwitch" #-} subscribe e sub))) spiderTimeline --TODO: Assert that the event isn't firing --TODO: This should not loop because none of the events should be firing, but still, it is inefficient
1907 subscription <- runReaderT (unSpiderHost (runFrame ({-# SCC "subscribeSwitch" #-} subscribe e sub))) spiderTimeline --TODO: Assert that the event isn't firing --TODO: This should not loop because none of the events should be firing, but still, it is inefficient
@@ -2074,9 +2102,9 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2074 {-# INLINABLE updated #-}
2102 {-# INLINABLE updated #-}
2075 updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
2103 updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
2076 {-# INLINABLE unsafeBuildDynamic #-}
2104 {-# INLINABLE unsafeBuildDynamic #-}
2077− unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeDyn (coerce readV0) $ coerce $ unSpiderEvent v'
2105+ unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
2078 {-# INLINABLE unsafeBuildIncremental #-}
2106 {-# INLINABLE unsafeBuildIncremental #-}
2079− unsafeBuildIncremental readV0 dv = SpiderIncremental $ dynamicDyn $ unsafeDyn (coerce readV0) $ unSpiderEvent dv
2107+ unsafeBuildIncremental readV0 dv = SpiderIncremental $ dynamicDyn $ unsafeBuildDynamic (coerce readV0) $ unSpiderEvent dv
2080 {-# INLINABLE mergeIncremental #-}
2108 {-# INLINABLE mergeIncremental #-}
2081 mergeIncremental = SpiderEvent . merge . (unsafeCoerce :: Dynamic x (PatchDMap k (R.Event (SpiderTimeline x))) -> Dynamic x (PatchDMap k (Event x))) . unSpiderIncremental
2109 mergeIncremental = SpiderEvent . merge . (unsafeCoerce :: Dynamic x (PatchDMap k (R.Event (SpiderTimeline x))) -> Dynamic x (PatchDMap k (Event x))) . unSpiderIncremental
2082 {-# INLINABLE mergeIncrementalWithMove #-}
2110 {-# INLINABLE mergeIncrementalWithMove #-}
@@ -2086,7 +2114,7 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
2086 {-# INLINABLE updatedIncremental #-}
2114 {-# INLINABLE updatedIncremental #-}
2087 updatedIncremental = SpiderEvent . dynamicUpdated . unSpiderIncremental
2115 updatedIncremental = SpiderEvent . dynamicUpdated . unSpiderIncremental
2088 {-# INLINABLE incrementalToDynamic #-}
2116 {-# INLINABLE incrementalToDynamic #-}
2089− incrementalToDynamic (SpiderIncremental i) = SpiderDynamic $ dynamicDynIdentity $ unsafeDyn (readBehaviorUntracked $ dynamicCurrent i) $ flip push (dynamicUpdated i) $ \p -> do
2117+ incrementalToDynamic (SpiderIncremental i) = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (readBehaviorUntracked $ dynamicCurrent i) $ flip push (dynamicUpdated i) $ \p -> do
2090 c <- readBehaviorUntracked $ dynamicCurrent i
2118 c <- readBehaviorUntracked $ dynamicCurrent i
2091 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
2119 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
2092 eventCoercion Coercion = Coercion
2120 eventCoercion Coercion = Coercion