@@ -171,6 +171,8 @@ fromChannelRaw sv = K.MkStream $ \st yld sng stp -> do
171171 ChildYield a -> yld a rest
172172 ChildStopChannel -> do
173173 liftIO (cleanupSVar (workerThreads sv))
174+ -- XXX drain all threads before stopping?
175+ -- XXX We can use a config option to drain or abort.
174176 cleanup >> stp
175177 ChildStop tid e -> do
176178 accountThread sv tid
@@ -188,6 +190,8 @@ fromChannelRaw sv = K.MkStream $ \st yld sng stp -> do
188190 -- K.foldStream st yld sng stp rest
189191 Nothing -> do
190192 liftIO (cleanupSVar (workerThreads sv))
193+ -- XXX Should we wait for all threads to abort
194+ -- before throwing the exception?
191195 cleanup >> throwM ex
192196
193197#ifdef INSPECTION
@@ -214,17 +218,20 @@ inspect $ hasNoTypeClassesExcept 'fromChannelRaw
214218-- XXX Add an option to block the consumer rather than stopping the stream if
215219-- the work queue gets over.
216220
217- chanCleanupOnGc :: Channel m a -> IO ()
218- chanCleanupOnGc chan = do
221+ chanCleanup :: String -> Channel m a -> IO ()
222+ chanCleanup reason chan = do
219223 when (svarInspectMode chan) $ do
220224 r <- liftIO $ readIORef (svarStopTime (svarStats chan))
221225 when (isNothing r) $
222- printSVar (dumpChannel chan) " Channel Garbage Collected "
226+ printSVar (dumpChannel chan) reason
223227 cleanupSVar (workerThreads chan)
224228 -- If there are any other channels referenced by this channel a GC will
225229 -- prompt them to be cleaned up quickly.
226230 when (svarInspectMode chan) performMajorGC
227231
232+ chanCleanupOnGc :: Channel m a -> IO ()
233+ chanCleanupOnGc = chanCleanup " Channel Garbage Collected"
234+
228235-- | Draw a stream from a concurrent channel. The stream consists of the
229236-- evaluated values from the input streams that were enqueued on the channel
230237-- using 'toChannelK'.
@@ -247,11 +254,15 @@ chanCleanupOnGc chan = do
247254--
248255-- CAUTION! This API must not be called more than once on a channel.
249256{-# INLINE fromChannelK #-}
250- fromChannelK :: MonadAsync m => Channel m a -> K. StreamK m a
251- fromChannelK chan =
257+ fromChannelK :: MonadAsync m => Maybe ( IO () -> IO () ) -> Channel m a -> K. StreamK m a
258+ fromChannelK register chan =
252259 K. mkStream $ \ st yld sng stp -> do
253260 ref <- liftIO $ newIORef ()
254261 _ <- liftIO $ mkWeakIORef ref (chanCleanupOnGc chan)
262+ let msg = " Channel cleanup via registered handler"
263+ case register of
264+ Nothing -> return ()
265+ Just f -> liftIO $ f (chanCleanup msg chan)
255266
256267 startChannel chan
257268 -- We pass a copy of sv to fromStreamVar, so that we know that it has
@@ -263,7 +274,8 @@ fromChannelK chan =
263274-- | A wrapper over 'fromChannelK' for 'Stream' type.
264275{-# INLINE fromChannel #-}
265276fromChannel :: MonadAsync m => Channel m a -> Stream m a
266- fromChannel = Stream. fromStreamK . fromChannelK
277+ -- XXX Pass the cleanup registration function to fromChannelK
278+ fromChannel = Stream. fromStreamK . fromChannelK Nothing
267279
268280#if __GLASGOW_HASKELL__ >= 810
269281type FromSVarState :: Type -> (Type -> Type ) -> Type -> Type
0 commit comments