@@ -73,10 +73,13 @@ import System.IO.Unsafe
73import System.Mem.Weak
73import System.Mem.Weak
74import Unsafe.Coerce
74import Unsafe.Coerce
76−#if defined(MIN_VERSION_semialign)
76+#ifdef MIN_VERSION_semialign
77#if MIN_VERSION_these(0,8,0)
77#if MIN_VERSION_these(0,8,0)
78import Data.These.Combinators (justThese)
78import Data.These.Combinators (justThese)
80+#if MIN_VERSION_semialign(1,1,0)
81+import Data.Zip (Zip (..))
82#ifdef DEBUG_CYCLES
85#ifdef DEBUG_CYCLES
@@ -103,6 +106,7 @@ import qualified Reflex.Host.Class
103import Reflex.NotReady.Class
106import Reflex.NotReady.Class
104import Reflex.Patch
107import Reflex.Patch
105import qualified Reflex.Patch.DMapWithMove as PatchDMapWithMove
108import qualified Reflex.Patch.DMapWithMove as PatchDMapWithMove
109+import Reflex.PerformEvent.Base (PerformEventT)
107#ifdef DEBUG_TRACE_EVENTS
111#ifdef DEBUG_TRACE_EVENTS
108import qualified Data.ByteString.Char8 as BS8
112import qualified Data.ByteString.Char8 as BS8
@@ -294,6 +298,7 @@ cacheEvent e =
295 subscribers <- liftIO FastWeakBag.empty
299 subscribers <- liftIO FastWeakBag.empty
296 occRef <- liftIO $ newIORef Nothing -- This should never be read prior to being set below
300 occRef <- liftIO $ newIORef Nothing -- This should never be read prior to being set below
297 (parentSub, occ) <- subscribeAndRead e $ debugSubscriber' ("cacheEvent" <> showNodeId' nodeId) $ Subscriber
302 (parentSub, occ) <- subscribeAndRead e $ debugSubscriber' ("cacheEvent" <> showNodeId' nodeId) $ Subscriber
298 { subscriberPropagate = \a -> do
303 { subscriberPropagate = \a -> do
299 -- checkCycle (_eventSubscription_subscribed parentSub)
304 -- checkCycle (_eventSubscription_subscribed parentSub)
@@ -303,6 +308,29 @@ cacheEvent e =
303 , subscriberInvalidateHeight = FastWeakBag.traverse subscribers . invalidateSubscriberHeight
308 , subscriberInvalidateHeight = FastWeakBag.traverse subscribers . invalidateSubscriberHeight
304 , subscriberRecalculateHeight = FastWeakBag.traverse subscribers . recalculateSubscriberHeight
309 , subscriberRecalculateHeight = FastWeakBag.traverse subscribers . recalculateSubscriberHeight
311+||||||| merged common ancestors
312+ (parentSub, occ) <- subscribeAndRead e $ Subscriber
313+ { subscriberPropagate = \a -> do
314+ liftIO $ writeIORef occRef $ Just a
315+ scheduleClear occRef
316+ propagateFast a subscribers
317+ , subscriberInvalidateHeight = \old -> do
318+ FastWeakBag.traverse subscribers $ invalidateSubscriberHeight old
319+ , subscriberRecalculateHeight = \new -> do
320+ FastWeakBag.traverse subscribers $ recalculateSubscriberHeight new
323+ (parentSub, occ) <- subscribeAndRead e $ Subscriber
324+ { subscriberPropagate = \a -> do
325+ liftIO $ writeIORef occRef $ Just a
326+ scheduleClear occRef
327+ propagateFast a subscribers
328+ , subscriberInvalidateHeight = \old -> do
329+ FastWeakBag.traverse_ subscribers $ invalidateSubscriberHeight old
330+ , subscriberRecalculateHeight = \new -> do
331+ FastWeakBag.traverse_ subscribers $ recalculateSubscriberHeight new
306 when (isJust occ) $ do
334 when (isJust occ) $ do
307 liftIO $ writeIORef occRef occ -- Set the initial value of occRef; we don't need to do this if occ is Nothing
335 liftIO $ writeIORef occRef occ -- Set the initial value of occRef; we don't need to do this if occ is Nothing
308 scheduleClear occRef
336 scheduleClear occRef
@@ -435,14 +463,12 @@ newSubscriberFan subscribed = debugSubscriber ("SubscriberFan " <> showNodeId su
435 return ()
463 return ()
436 , subscriberInvalidateHeight = \old -> do
464 , subscriberInvalidateHeight = \old -> do
437 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
465 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
438− forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse (_fanSubscribedChildren_list v) $ invalidateSubscriberHeight old
466+ forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse_ (_fanSubscribedChildren_list v) $ invalidateSubscriberHeight old
440 , subscriberRecalculateHeight = \new -> do
467 , subscriberRecalculateHeight = \new -> do
441 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
468 subscribers <- readIORef $ fanSubscribedSubscribers subscribed
442− forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse (_fanSubscribedChildren_list v) $ recalculateSubscriberHeight new
469+ forM_ (DMap.toList subscribers) $ \(_ :=> v) -> WeakBag.traverse_ (_fanSubscribedChildren_list v) $ recalculateSubscriberHeight new
446newSubscriberSwitch :: forall x a. HasSpiderTimeline x => SwitchSubscribed x a -> IO (Subscriber x a)
472newSubscriberSwitch :: forall x a. HasSpiderTimeline x => SwitchSubscribed x a -> IO (Subscriber x a)
447newSubscriberSwitch subscribed = debugSubscriber ("SubscriberCoincidenceOuter" <> showNodeId subscribed) $ Subscriber
473newSubscriberSwitch subscribed = debugSubscriber ("SubscriberCoincidenceOuter" <> showNodeId subscribed) $ Subscriber
448 { subscriberPropagate = \a -> {-# SCC "traverseSwitch" #-} do
474 { subscriberPropagate = \a -> {-# SCC "traverseSwitch" #-} do
@@ -453,7 +479,7 @@ newSubscriberSwitch subscribed = debugSubscriber ("SubscriberCoincidenceOuter" <
453 oldHeight <- readIORef $ switchSubscribedHeight subscribed
479 oldHeight <- readIORef $ switchSubscribedHeight subscribed
454 when (oldHeight /= invalidHeight) $ do
480 when (oldHeight /= invalidHeight) $ do
455 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
481 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
456− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
482+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
457 , subscriberRecalculateHeight = (`updateSwitchHeight` subscribed)
483 , subscriberRecalculateHeight = (`updateSwitchHeight` subscribed)
@@ -472,8 +498,8 @@ newSubscriberCoincidenceOuter subscribed = debugSubscriber ("SubscriberCoinciden
472 Nothing ->
498 Nothing ->
473 when (innerHeight > outerHeight) $ liftIO $ do -- If the event fires, it will fire at a later height
499 when (innerHeight > outerHeight) $ liftIO $ do -- If the event fires, it will fire at a later height
474 writeIORef (coincidenceSubscribedHeight subscribed) $! innerHeight
500 writeIORef (coincidenceSubscribedHeight subscribed) $! innerHeight
475− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight outerHeight
501+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight outerHeight
476− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight innerHeight
502+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight innerHeight
477 Just o -> do -- Since it's already firing, no need to adjust height
503 Just o -> do -- Since it's already firing, no need to adjust height
478 liftIO $ writeIORef (coincidenceSubscribedOccurrence subscribed) occ
504 liftIO $ writeIORef (coincidenceSubscribedOccurrence subscribed) occ
479 scheduleClear $ coincidenceSubscribedOccurrence subscribed
505 scheduleClear $ coincidenceSubscribedOccurrence subscribed
@@ -507,14 +533,14 @@ propagate :: forall x a. HasSpiderTimeline x => a -> WeakBag (Subscriber x a) ->
507propagate a subscribers = withIncreasedDepth (Proxy::Proxy x) $
533propagate a subscribers = withIncreasedDepth (Proxy::Proxy x) $
508 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
534 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
509 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
535 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
510− WeakBag.traverse subscribers $ \s -> subscriberPropagate s a
536+ WeakBag.traverse_ subscribers $ \s -> subscriberPropagate s a
512-- | Propagate everything at the current height
538-- | Propagate everything at the current height
513propagateFast :: forall x a. HasSpiderTimeline x => a -> FastWeakBag (Subscriber x a) -> EventM x ()
539propagateFast :: forall x a. HasSpiderTimeline x => a -> FastWeakBag (Subscriber x a) -> EventM x ()
514propagateFast a subscribers = withIncreasedDepth (Proxy::Proxy x) $
540propagateFast a subscribers = withIncreasedDepth (Proxy::Proxy x) $
515 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
541 -- Note: in the following traversal, we do not visit nodes that are added to the list during our traversal; they are new events, which will necessarily have full information already, so there is no need to traverse them
516 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
542 --TODO: Should we check if nodes already have their values before propagating? Maybe we're re-doing work
517− FastWeakBag.traverse subscribers $ \s -> subscriberPropagate s a
543+ FastWeakBag.traverse_ subscribers $ \s -> subscriberPropagate s a
519--------------------------------------------------------------------------------
545--------------------------------------------------------------------------------
520-- EventSubscribed
546-- EventSubscribed
@@ -1139,7 +1165,10 @@ instance HasSpiderTimeline x => Semialign (Event x) where
1139 align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
1165 align ea eb = mapMaybe dmapToThese $ mergeG coerce $ dynamicConst $
1140 DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1166 DMap.fromDistinctAscList [LeftTag :=> ea, RightTag :=> eb]
1142−#if defined(MIN_VERSION_semialign)
1168+#ifdef MIN_VERSION_semialign
1169+#if MIN_VERSION_semialign(1,1,0)
1170+instance HasSpiderTimeline x => Zip (Event x) where
1143 zip x y = mapMaybe justThese $ align x y
1172 zip x y = mapMaybe justThese $ align x y
@@ -1587,15 +1616,15 @@ fanInt p = unsafePerformIO $ do
1587 liftIO $ writeIORef (_fanInt_occRef self) m
1616 liftIO $ writeIORef (_fanInt_occRef self) m
1588 scheduleIntClear $ _fanInt_occRef self
1617 scheduleIntClear $ _fanInt_occRef self
1589 FastMutableIntMap.forIntersectionWithImmutable_ (_fanInt_subscribers self) m $ \b v -> --TODO: Do we need to know that no subscribers are being added as we traverse?
1618 FastMutableIntMap.forIntersectionWithImmutable_ (_fanInt_subscribers self) m $ \b v -> --TODO: Do we need to know that no subscribers are being added as we traverse?
1590− FastWeakBag.traverse b $ \s ->
1619+ FastWeakBag.traverse_ b $ \s ->
1591 subscriberPropagate s v
1620 subscriberPropagate s v
1592 , subscriberInvalidateHeight = \old ->
1621 , subscriberInvalidateHeight = \old ->
1593 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b ->
1622 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b ->
1594− FastWeakBag.traverse b $ \s ->
1623+ FastWeakBag.traverse_ b $ \s ->
1595 subscriberInvalidateHeight s old
1624 subscriberInvalidateHeight s old
1596 , subscriberRecalculateHeight = \new ->
1625 , subscriberRecalculateHeight = \new ->
1597 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b ->
1626 FastMutableIntMap.for_ (_fanInt_subscribers self) $ \b ->
1598− FastWeakBag.traverse b $ \s ->
1627+ FastWeakBag.traverse_ b $ \s ->
1599 subscriberRecalculateHeight s new
1628 subscriberRecalculateHeight s new
1601 liftIO $ do
1630 liftIO $ do
@@ -2326,7 +2355,7 @@ runFrame a = SpiderHost $ do
2326 myHeight <- readIORef $ switchSubscribedHeight subscribed
2355 myHeight <- readIORef $ switchSubscribedHeight subscribed
2327 when (parentHeight /= myHeight) $ do
2356 when (parentHeight /= myHeight) $ do
2328 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
2357 writeIORef (switchSubscribedHeight subscribed) $! invalidHeight
2329− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight myHeight
2358+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ invalidateSubscriberHeight myHeight
2330 mapM_ _someMergeUpdate_invalidateHeight mergeUpdates --TODO: In addition to when the patch is completely empty, we should also not run this if it has some Nothing values, but none of them have actually had any effect; potentially, we could even check for Just values with no effect (e.g. by comparing their IORefs and ignoring them if they are unchanged); actually, we could just check if the new height is different
2359 mapM_ _someMergeUpdate_invalidateHeight mergeUpdates --TODO: In addition to when the patch is completely empty, we should also not run this if it has some Nothing values, but none of them have actually had any effect; potentially, we could even check for Just values with no effect (e.g. by comparing their IORefs and ignoring them if they are unchanged); actually, we could just check if the new height is different
2331 forM_ coincidenceInfos $ \(SomeResetCoincidence subscription mcs) -> do
2360 forM_ coincidenceInfos $ \(SomeResetCoincidence subscription mcs) -> do
2332 unsubscribe subscription
2361 unsubscribe subscription
@@ -2367,7 +2396,7 @@ invalidateCoincidenceHeight subscribed = do
2367 oldHeight <- readIORef $ coincidenceSubscribedHeight subscribed
2396 oldHeight <- readIORef $ coincidenceSubscribedHeight subscribed
2368 when (oldHeight /= invalidHeight) $ do
2397 when (oldHeight /= invalidHeight) $ do
2369 writeIORef (coincidenceSubscribedHeight subscribed) $! invalidHeight
2398 writeIORef (coincidenceSubscribedHeight subscribed) $! invalidHeight
2370− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
2399+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ invalidateSubscriberHeight oldHeight
2372updateSwitchHeight :: Height -> SwitchSubscribed x a -> IO ()
2401updateSwitchHeight :: Height -> SwitchSubscribed x a -> IO ()
2373updateSwitchHeight new subscribed = do
2402updateSwitchHeight new subscribed = do
@@ -2375,7 +2404,7 @@ updateSwitchHeight new subscribed = do
2375 when (oldHeight == invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2404 when (oldHeight == invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2376 when (new /= invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2405 when (new /= invalidHeight) $ do --TODO: This 'when' should probably be an assertion
2377 writeIORef (switchSubscribedHeight subscribed) $! new
2406 writeIORef (switchSubscribedHeight subscribed) $! new
2378− WeakBag.traverse (switchSubscribedSubscribers subscribed) $ recalculateSubscriberHeight new
2407+ WeakBag.traverse_ (switchSubscribedSubscribers subscribed) $ recalculateSubscriberHeight new
2380recalculateCoincidenceHeight :: CoincidenceSubscribed x a -> IO ()
2409recalculateCoincidenceHeight :: CoincidenceSubscribed x a -> IO ()
2381recalculateCoincidenceHeight subscribed = do
2410recalculateCoincidenceHeight subscribed = do
@@ -2384,7 +2413,7 @@ recalculateCoincidenceHeight subscribed = do
2384 height <- calculateCoincidenceHeight subscribed
2413 height <- calculateCoincidenceHeight subscribed
2385 when (height /= invalidHeight) $ do
2414 when (height /= invalidHeight) $ do
2386 writeIORef (coincidenceSubscribedHeight subscribed) $! height
2415 writeIORef (coincidenceSubscribedHeight subscribed) $! height
2387− WeakBag.traverse (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight height
2416+ WeakBag.traverse_ (coincidenceSubscribedSubscribers subscribed) $ recalculateSubscriberHeight height
2389calculateSwitchHeight :: SwitchSubscribed x a -> IO Height
2418calculateSwitchHeight :: SwitchSubscribed x a -> IO Height
2390calculateSwitchHeight subscribed = getEventSubscribedHeight . _eventSubscription_subscribed =<< readIORef (switchSubscribedCurrentParent subscribed)
2419calculateSwitchHeight subscribed = getEventSubscribedHeight . _eventSubscription_subscribed =<< readIORef (switchSubscribedCurrentParent subscribed)
@@ -2824,3 +2853,11 @@ instance MonadAtomicRef (SpiderHostFrame x) where
2824instance PrimMonad (SpiderHostFrame x) where
2853instance PrimMonad (SpiderHostFrame x) where
2825 type PrimState (SpiderHostFrame x) = PrimState IO
2854 type PrimState (SpiderHostFrame x) = PrimState IO
2826 primitive = SpiderHostFrame . EventM . primitive
2855 primitive = SpiderHostFrame . EventM . primitive
2857+instance NotReady (SpiderTimeline x) (SpiderHost x) where
2858+ notReadyUntil _ = return ()
2859+ notReady = return ()
2861+instance HasSpiderTimeline x => NotReady (SpiderTimeline x) (PerformEventT (SpiderTimeline x) (SpiderHost x)) where
2862+ notReadyUntil _ = return ()
2863+ notReady = return ()