getMergeSubscribed :: forall k. GCompare k => Merge k -> EventM (MergeSubscribed k)
getMergeSubscribed m = {-# SCC "getMergeSubscribed.entire" #-} do
  mSubscribed <- liftIO $ readIORef $ mergeSubscribed m
  case mSubscribed of
    Just subscribed -> return subscribed
    Nothing -> if DMap.null $ mergeParents m then emptyMergeSubscribed else do
      subscribedRef <- liftIO $ newIORef $ error "getMergeSubscribed: subscribedRef not yet initialized"
      subscribedUnsafe <- liftIO $ unsafeInterleaveIO $ readIORef subscribedRef
      s <- liftIO $ newBox subscribedUnsafe
      ws <- liftIO $ mkWeakPtrWithDebug s "SubscriberMerge"
      subscribers :: [(Any, Maybe (DSum k), Int, DSum (WrapArg EventSubscribed k))] <- forM (DMap.toList $ mergeParents m) $ {-# SCC "getMergeSubscribed.a" #-} \(WrapArg k :=> e) -> {-# SCC "getMergeSubscribed.a1" #-} do
        parentSubd <- {-# SCC "getMergeSubscribed.a.parentSubd" #-} subscribe e $ WeakSubscriberMerge k ws
        parentOcc <- {-# SCC "getMergeSubscribed.a.parentOcc" #-} liftIO $ getEventSubscribedOcc parentSubd
        height <- {-# SCC "getMergeSubscribed.a.height" #-} liftIO $ readIORef $ eventSubscribedHeightRef parentSubd
        return $ {-# SCC "getMergeSubscribed.a.returnVal" #-} (unsafeCoerce s :: Any, fmap (k :=>) parentOcc, height, WrapArg k :=> parentSubd)
      let dm = DMap.fromDistinctAscList $ catMaybes $ map (\(_, x, _, _) -> x) subscribers
          subscriberHeights = map (\(_, _, x, _) -> x) subscribers
          myHeight =
            if any (==invalidHeight) subscriberHeights --TODO: Replace 'any' with invalidHeight-preserving 'maximum'
            then invalidHeight
            else succ $ Prelude.maximum subscriberHeights -- This is safe because the DMap will never be empty here
      currentHeight <- getCurrentHeight
      let (occ, accum) = if currentHeight >= myHeight -- If we should have fired by now
                         then (if DMap.null dm then Nothing else Just dm, DMap.empty)
                         else (Nothing, dm)
      when (not $ DMap.null accum) $ do
        scheduleMerge myHeight subscribedUnsafe
      occRef <- liftIO $ newIORef occ
      when (isJust occ) $ scheduleClear occRef
      accumRef <- liftIO $ newIORef accum
      heightRef <- liftIO $ newIORef myHeight
      subsRef <- liftIO $ newIORef []
      let subscribed = MergeSubscribed
            { mergeSubscribedOccurrence = occRef
            , mergeSubscribedAccum = accumRef
            , mergeSubscribedHeight = heightRef
            , mergeSubscribedSubscribers = subsRef
            , mergeSubscribedSelf = unsafeCoerce $ map (\(x, _, _, _) -> x) subscribers --TODO: Does lack of strictness make this leak?
            , mergeSubscribedParents = DMap.fromDistinctAscList $ map (\(_, _, _, x) -> x) subscribers
#ifdef DEBUG_NODEIDS
            , mergeSubscribedNodeId = unsafeNodeId m
#endif
            }
      liftIO $ writeIORef subscribedRef subscribed
      return subscribed
  where emptyMergeSubscribed = do --TODO: This should never happen
          occRef <- liftIO $ newIORef Nothing
          accumRef <- liftIO $ newIORef DMap.empty
          subsRef <- liftIO $ newIORef []
          return $ MergeSubscribed
            { mergeSubscribedOccurrence = occRef
            , mergeSubscribedAccum = accumRef
            , mergeSubscribedHeight = zeroRef
            , mergeSubscribedSubscribers = subsRef --TODO: This will definitely leak
            , mergeSubscribedSelf = unsafeCoerce ()
            , mergeSubscribedParents = DMap.empty
#ifdef DEBUG_NODEIDS
            , mergeSubscribedNodeId = -1
#endif
            }
getMergeSubscribed :: forall k. GCompare k => Merge k -> EventM (MergeSubscribed k)
getMergeSubscribed m = {-# SCC "getMergeSubscribed.entire" #-} do
  mSubscribed <- liftIO $ readIORef $ mergeSubscribed m
  case mSubscribed of
    Just subscribed -> return subscribed
    Nothing -> if DMap.null $ mergeParents m then emptyMergeSubscribed else do
      subscribedRef <- liftIO $ newIORef $ error "getMergeSubscribed: subscribedRef not yet initialized"
      subscribedUnsafe <- liftIO $ unsafeInterleaveIO $ readIORef subscribedRef
      s <- liftIO $ newBox subscribedUnsafe
      ws <- liftIO $ mkWeakPtrWithDebug s "SubscriberMerge"
      subscribers :: [(Any, Maybe (DSum k), Int, DSum (WrapArg EventSubscribed k))] <- forM (DMap.toList $ mergeParents m) $ {-# SCC "getMergeSubscribed.a" #-} \(WrapArg k :=> e) -> {-# SCC "getMergeSubscribed.a1" #-} do
        parentSubd <- {-# SCC "getMergeSubscribed.a.parentSubd" #-} subscribe e $ WeakSubscriberMerge k ws
        parentOcc <- {-# SCC "getMergeSubscribed.a.parentOcc" #-} liftIO $ getEventSubscribedOcc parentSubd
        height <- {-# SCC "getMergeSubscribed.a.height" #-} liftIO $ readIORef $ eventSubscribedHeightRef parentSubd
        return $ {-# SCC "getMergeSubscribed.a.returnVal" #-} (unsafeCoerce s :: Any, fmap (k :=>) parentOcc, height, WrapArg k :=> parentSubd)
      let dm = DMap.fromDistinctAscList $ catMaybes $ map (\(_, x, _, _) -> x) subscribers
          subscriberHeights = map (\(_, _, x, _) -> x) subscribers
          myHeight =
            if any (==invalidHeight) subscriberHeights --TODO: Replace 'any' with invalidHeight-preserving 'maximum'
            then invalidHeight
            else succ $ Prelude.maximum subscriberHeights -- This is safe because the DMap will never be empty here
      currentHeight <- getCurrentHeight
      let (occ, accum) = if currentHeight >= myHeight -- If we should have fired by now
                         then (if DMap.null dm then Nothing else Just dm, DMap.empty)
                         else (Nothing, dm)
      when (not $ DMap.null accum) $ do
        scheduleMerge myHeight subscribedUnsafe
      occRef <- liftIO $ newIORef occ
      when (isJust occ) $ scheduleClear occRef
      accumRef <- liftIO $ newIORef accum
      heightRef <- liftIO $ newIORef myHeight
      subsRef <- liftIO $ newIORef []
      let subscribed = MergeSubscribed
            { mergeSubscribedOccurrence = occRef
            , mergeSubscribedAccum = accumRef
            , mergeSubscribedHeight = heightRef
            , mergeSubscribedSubscribers = subsRef
            , mergeSubscribedSelf = unsafeCoerce $ map (\(x, _, _, _) -> x) subscribers --TODO: Does lack of strictness make this leak?
            , mergeSubscribedParents = DMap.fromDistinctAscList $ map (\(_, _, _, x) -> x) subscribers
#ifdef DEBUG_NODEIDS
            , mergeSubscribedNodeId = unsafeNodeId m
#endif
            }
      liftIO $ writeIORef subscribedRef subscribed
      return subscribed
  where emptyMergeSubscribed = do --TODO: This should never happen
          occRef <- liftIO $ newIORef Nothing
          accumRef <- liftIO $ newIORef DMap.empty
          subsRef <- liftIO $ newIORef []
          return $ MergeSubscribed
            { mergeSubscribedOccurrence = occRef
            , mergeSubscribedAccum = accumRef
            , mergeSubscribedHeight = zeroRef
            , mergeSubscribedSubscribers = subsRef --TODO: This will definitely leak
            , mergeSubscribedSelf = unsafeCoerce ()
            , mergeSubscribedParents = DMap.empty
#ifdef DEBUG_NODEIDS
            , mergeSubscribedNodeId = -1
#endif
            }
getMergeSubscribed m = {-# SCC "getMergeSubscribed.entire" #-} do
  mSubscribed <- liftIO $ readIORef $ mergeSubscribed m
  case mSubscribed of
    Just subscribed -> return subscribed
    Nothing -> if DMap.null $ mergeParents m then emptyMergeSubscribed else do
      subscribedRef <- liftIO $ newIORef $ error "getMergeSubscribed: subscribedRef not yet initialized"
      subscribedUnsafe <- liftIO $ unsafeInterleaveIO $ readIORef subscribedRef
      s <- liftIO $ newBox subscribedUnsafe
      ws <- liftIO $ mkWeakPtrWithDebug s "SubscriberMerge"
      subscribers :: [(Any, Maybe (DSum k), Int, DSum (WrapArg EventSubscribed k))] <- forM (DMap.toList $ mergeParents m) $ {-# SCC "getMergeSubscribed.a" #-} \(WrapArg k :=> e) -> {-# SCC "getMergeSubscribed.a1" #-} do
        parentSubd <- {-# SCC "getMergeSubscribed.a.parentSubd" #-} subscribe e $ WeakSubscriberMerge k ws
        parentOcc <- {-# SCC "getMergeSubscribed.a.parentOcc" #-} liftIO $ getEventSubscribedOcc parentSubd
        height <- {-# SCC "getMergeSubscribed.a.height" #-} liftIO $ readIORef $ eventSubscribedHeightRef parentSubd
        return $ {-# SCC "getMergeSubscribed.a.returnVal" #-} (unsafeCoerce s :: Any, fmap (k :=>) parentOcc, height, WrapArg k :=> parentSubd)
      let dm = DMap.fromDistinctAscList $ catMaybes $ map (\(_, x, _, _) -> x) subscribers
          subscriberHeights = map (\(_, _, x, _) -> x) subscribers
          myHeight =
            if any (==invalidHeight) subscriberHeights --TODO: Replace 'any' with invalidHeight-preserving 'maximum'
            then invalidHeight
            else succ $ Prelude.maximum subscriberHeights -- This is safe because the DMap will never be empty here
      currentHeight <- getCurrentHeight
      let (occ, accum) = if currentHeight >= myHeight -- If we should have fired by now
                         then (if DMap.null dm then Nothing else Just dm, DMap.empty)
                         else (Nothing, dm)
      when (not $ DMap.null accum) $ do
        scheduleMerge myHeight subscribedUnsafe
      occRef <- liftIO $ newIORef occ
      when (isJust occ) $ scheduleClear occRef
      accumRef <- liftIO $ newIORef accum
      heightRef <- liftIO $ newIORef myHeight
      subsRef <- liftIO $ newIORef []
      let subscribed = MergeSubscribed
            { mergeSubscribedOccurrence = occRef
            , mergeSubscribedAccum = accumRef
            , mergeSubscribedHeight = heightRef
            , mergeSubscribedSubscribers = subsRef
            , mergeSubscribedSelf = unsafeCoerce $ map (\(x, _, _, _) -> x) subscribers --TODO: Does lack of strictness make this leak?
            , mergeSubscribedParents = DMap.fromDistinctAscList $ map (\(_, _, _, x) -> x) subscribers
#ifdef DEBUG_NODEIDS
            , mergeSubscribedNodeId = unsafeNodeId m
#endif
            }
      liftIO $ writeIORef subscribedRef subscribed
      return subscribed
  where emptyMergeSubscribed = do --TODO: This should never happen
          occRef <- liftIO $ newIORef Nothing
          accumRef <- liftIO $ newIORef DMap.empty
          subsRef <- liftIO $ newIORef []
          return $ MergeSubscribed
            { mergeSubscribedOccurrence = occRef
            , mergeSubscribedAccum = accumRef
            , mergeSubscribedHeight = zeroRef
            , mergeSubscribedSubscribers = subsRef --TODO: This will definitely leak
            , mergeSubscribedSelf = unsafeCoerce ()
            , mergeSubscribedParents = DMap.empty
#ifdef DEBUG_NODEIDS
            , mergeSubscribedNodeId = -1
#endif
            }