@@ -57,6 +57,10 @@ import GHC.Exts
5757import GHC.IO hiding (finally , onException )
5858import GHC.Conc (ThreadId (.. ), labelThread )
5959
60+ #ifdef DEBUG_AUTO_LABEL
61+ import GHC.Stack
62+ #endif
63+
6064-- -----------------------------------------------------------------------------
6165-- STM Async API
6266
@@ -95,40 +99,65 @@ compareAsyncs (Async t1 _) (Async t2 _) = compare t1 t2
9599-- (see module-level documentation for details).
96100--
97101-- __Use 'withAsync' style functions wherever you can instead!__
98- async :: IO a -> IO (Async a )
102+ async ::
103+ #ifdef DEBUG_AUTO_LABEL
104+ HasCallStack =>
105+ #endif
106+ IO a -> IO (Async a)
99107async = inline asyncUsing rawForkIO
100108
101109-- | Like 'async' but using 'forkOS' internally.
102- asyncBound :: IO a -> IO (Async a )
110+ asyncBound ::
111+ #ifdef DEBUG_AUTO_LABEL
112+ HasCallStack =>
113+ #endif
114+ IO a -> IO (Async a)
103115asyncBound = asyncUsing forkOS
104116
105117-- | Like 'async' but using 'forkOn' internally.
106- asyncOn :: Int -> IO a -> IO (Async a )
118+ asyncOn ::
119+ #ifdef DEBUG_AUTO_LABEL
120+ HasCallStack =>
121+ #endif
122+ Int -> IO a -> IO (Async a)
107123asyncOn = asyncUsing . rawForkOn
108124
109125-- | Like 'async' but using 'forkIOWithUnmask' internally. The child
110126-- thread is passed a function that can be used to unmask asynchronous
111127-- exceptions.
112- asyncWithUnmask :: ((forall b . IO b -> IO b ) -> IO a ) -> IO (Async a )
128+ asyncWithUnmask ::
129+ #ifdef DEBUG_AUTO_LABEL
130+ HasCallStack =>
131+ #endif
132+ ((forall b . IO b -> IO b) -> IO a) -> IO (Async a)
113133asyncWithUnmask actionWith = asyncUsing rawForkIO (actionWith unsafeUnmask)
114134
115135-- | Like 'asyncOn' but using 'forkOnWithUnmask' internally. The
116136-- child thread is passed a function that can be used to unmask
117137-- asynchronous exceptions.
118- asyncOnWithUnmask :: Int -> ((forall b . IO b -> IO b ) -> IO a ) -> IO (Async a )
138+ asyncOnWithUnmask ::
139+ #ifdef DEBUG_AUTO_LABEL
140+ HasCallStack =>
141+ #endif
142+ Int -> ((forall b . IO b -> IO b) -> IO a) -> IO (Async a)
119143asyncOnWithUnmask cpu actionWith =
120144 asyncUsing (rawForkOn cpu) (actionWith unsafeUnmask)
121145
122- asyncUsing :: (IO () -> IO ThreadId )
123- -> IO a -> IO (Async a )
146+ asyncUsing ::
147+ #ifdef DEBUG_AUTO_LABEL
148+ HasCallStack =>
149+ #endif
150+ (IO () -> IO ThreadId ) -> IO a -> IO (Async a)
124151asyncUsing doFork = \ action -> do
125152 var <- newEmptyTMVarIO
153+ let action_plus = debugLabelMe >> action
126154 -- t <- forkFinally action (\r -> atomically $ putTMVar var r)
127155 -- slightly faster:
128156 t <- mask $ \ restore ->
129- doFork $ try (restore action ) >>= atomically . putTMVar var
157+ doFork $ try (restore action_plus ) >>= atomically . putTMVar var
130158 return (Async t (readTMVar var))
131159
160+
132161-- | Spawn an asynchronous action in a separate thread, and pass its
133162-- @Async@ handle to the supplied function. When the function returns
134163-- or throws an exception, 'uninterruptibleCancel' is called on the @Async@.
@@ -144,41 +173,63 @@ asyncUsing doFork = \action -> do
144173-- to `withAsync` returns, so nesting many `withAsync` calls requires
145174-- linear memory.
146175--
147- withAsync :: IO a -> (Async a -> IO b ) -> IO b
176+ withAsync ::
177+ #ifdef DEBUG_AUTO_LABEL
178+ HasCallStack =>
179+ #endif
180+ IO a -> (Async a -> IO b) -> IO b
148181withAsync = inline withAsyncUsing rawForkIO
149182
150183-- | Like 'withAsync' but uses 'forkOS' internally.
151- withAsyncBound :: IO a -> (Async a -> IO b ) -> IO b
184+ withAsyncBound ::
185+ #ifdef DEBUG_AUTO_LABEL
186+ HasCallStack =>
187+ #endif
188+ IO a -> (Async a -> IO b) -> IO b
152189withAsyncBound = withAsyncUsing forkOS
153190
154191-- | Like 'withAsync' but uses 'forkOn' internally.
155- withAsyncOn :: Int -> IO a -> (Async a -> IO b ) -> IO b
192+ withAsyncOn ::
193+ #ifdef DEBUG_AUTO_LABEL
194+ HasCallStack =>
195+ #endif
196+ Int -> IO a -> (Async a -> IO b) -> IO b
156197withAsyncOn = withAsyncUsing . rawForkOn
157198
158199-- | Like 'withAsync' but uses 'forkIOWithUnmask' internally. The
159200-- child thread is passed a function that can be used to unmask
160201-- asynchronous exceptions.
161- withAsyncWithUnmask
162- :: ((forall c . IO c -> IO c ) -> IO a ) -> (Async a -> IO b ) -> IO b
202+ withAsyncWithUnmask ::
203+ #ifdef DEBUG_AUTO_LABEL
204+ HasCallStack =>
205+ #endif
206+ ((forall c. IO c -> IO c) -> IO a) -> (Async a -> IO b) -> IO b
163207withAsyncWithUnmask actionWith =
164208 withAsyncUsing rawForkIO (actionWith unsafeUnmask)
165209
166210-- | Like 'withAsyncOn' but uses 'forkOnWithUnmask' internally. The
167211-- child thread is passed a function that can be used to unmask
168212-- asynchronous exceptions
169- withAsyncOnWithUnmask
170- :: Int -> ((forall c . IO c -> IO c ) -> IO a ) -> (Async a -> IO b ) -> IO b
213+ withAsyncOnWithUnmask ::
214+ #ifdef DEBUG_AUTO_LABEL
215+ HasCallStack =>
216+ #endif
217+ Int -> ((forall c. IO c -> IO c) -> IO a) -> (Async a -> IO b) -> IO b
171218withAsyncOnWithUnmask cpu actionWith =
172219 withAsyncUsing (rawForkOn cpu) (actionWith unsafeUnmask)
173220
174- withAsyncUsing :: (IO () -> IO ThreadId )
175- -> IO a -> (Async a -> IO b ) -> IO b
221+ withAsyncUsing ::
222+ #ifdef DEBUG_AUTO_LABEL
223+ HasCallStack =>
224+ #endif
225+ (IO () -> IO ThreadId ) -> IO a -> (Async a -> IO b) -> IO b
176226-- The bracket version works, but is slow. We can do better by
177227-- hand-coding it:
178228withAsyncUsing doFork = \ action inner -> do
179229 var <- newEmptyTMVarIO
180230 mask $ \ restore -> do
181- t <- doFork $ try (restore action) >>= atomically . putTMVar var
231+ let action_plus = debugLabelMe >> action
232+ t <- doFork $ try (restore action_plus) >>= atomically . putTMVar var
182233 let a = Async t (readTMVar var)
183234 r <- restore (inner a) `catchAll` \ e -> do
184235 uninterruptibleCancel a
@@ -555,11 +606,19 @@ isCancel e
555606-- > withAsync right $ \b ->
556607-- > waitEither a b
557608--
558- race :: IO a -> IO b -> IO (Either a b )
609+ race ::
610+ #ifdef DEBUG_AUTO_LABEL
611+ HasCallStack =>
612+ #endif
613+ IO a -> IO b -> IO (Either a b)
559614
560615-- | Like 'race', but the result is ignored.
561616--
562- race_ :: IO a -> IO b -> IO ()
617+ race_ ::
618+ #ifdef DEBUG_AUTO_LABEL
619+ HasCallStack =>
620+ #endif
621+ IO a -> IO b -> IO ()
563622
564623
565624-- | Run two @IO@ actions concurrently, and return both results. If
@@ -571,19 +630,31 @@ race_ :: IO a -> IO b -> IO ()
571630-- > withAsync left $ \a ->
572631-- > withAsync right $ \b ->
573632-- > waitBoth a b
574- concurrently :: IO a -> IO b -> IO (a ,b )
633+ concurrently ::
634+ #ifdef DEBUG_AUTO_LABEL
635+ HasCallStack =>
636+ #endif
637+ IO a -> IO b -> IO (a,b)
575638
576639
577640-- | Run two @IO@ actions concurrently. If both of them end with @Right@,
578641-- return both results. If one of then ends with @Left@, interrupt the other
579642-- action and return the @Left@.
580643--
581- concurrentlyE :: IO (Either e a ) -> IO (Either e b ) -> IO (Either e (a , b ))
644+ concurrentlyE ::
645+ #ifdef DEBUG_AUTO_LABEL
646+ HasCallStack =>
647+ #endif
648+ IO (Either e a) -> IO (Either e b) -> IO (Either e (a, b))
582649
583650-- | 'concurrently', but ignore the result values
584651--
585652-- @since 2.1.1
586- concurrently_ :: IO a -> IO b -> IO ()
653+ concurrently_ ::
654+ #ifdef DEBUG_AUTO_LABEL
655+ HasCallStack =>
656+ #endif
657+ IO a -> IO b -> IO ()
587658
588659#define USE_ASYNC_VERSIONS 0
589660
@@ -644,9 +715,13 @@ concurrentlyE left right = concurrently' left right (collect [])
644715 Left ex -> throwIO ex
645716 Right r -> collect (r: xs) m
646717
647- concurrently' :: IO a -> IO b
648- -> (IO (Either SomeException (Either a b )) -> IO r )
649- -> IO r
718+ concurrently' ::
719+ #ifdef DEBUG_AUTO_LABEL
720+ HasCallStack =>
721+ #endif
722+ IO a -> IO b
723+ -> (IO (Either SomeException (Either a b)) -> IO r)
724+ -> IO r
650725concurrently' left right collect = do
651726 done <- newEmptyMVar
652727 mask $ \ restore -> do
@@ -723,37 +798,61 @@ concurrently_ left right = concurrently' left right (collect 0)
723798-- for each element of the @Traversable@, so running this on large
724799-- inputs without care may lead to resource exhaustion (of memory,
725800-- file descriptors, or other limited resources).
726- mapConcurrently :: Traversable t => (a -> IO b ) -> t a -> IO (t b )
801+ mapConcurrently ::
802+ #ifdef DEBUG_AUTO_LABEL
803+ HasCallStack =>
804+ #endif
805+ Traversable t => (a -> IO b) -> t a -> IO (t b)
727806mapConcurrently f = runConcurrently . traverse (Concurrently . f)
728807
729808-- | `forConcurrently` is `mapConcurrently` with its arguments flipped
730809--
731810-- > pages <- forConcurrently ["url1", "url2", "url3"] $ \url -> getURL url
732811--
733812-- @since 2.1.0
734- forConcurrently :: Traversable t => t a -> (a -> IO b ) -> IO (t b )
813+ forConcurrently ::
814+ #ifdef DEBUG_AUTO_LABEL
815+ HasCallStack =>
816+ #endif
817+ Traversable t => t a -> (a -> IO b) -> IO (t b)
735818forConcurrently = flip mapConcurrently
736819
737820-- | `mapConcurrently_` is `mapConcurrently` with the return value discarded;
738821-- a concurrent equivalent of 'mapM_'.
739- mapConcurrently_ :: F. Foldable f => (a -> IO b ) -> f a -> IO ()
822+ mapConcurrently_ ::
823+ #ifdef DEBUG_AUTO_LABEL
824+ HasCallStack =>
825+ #endif
826+ F. Foldable f => (a -> IO b) -> f a -> IO ()
740827mapConcurrently_ f = runConcurrently . F. foldMap (Concurrently . void . f)
741828
742829-- | `forConcurrently_` is `forConcurrently` with the return value discarded;
743830-- a concurrent equivalent of 'forM_'.
744- forConcurrently_ :: F. Foldable f => f a -> (a -> IO b ) -> IO ()
831+ forConcurrently_ ::
832+ #ifdef DEBUG_AUTO_LABEL
833+ HasCallStack =>
834+ #endif
835+ F. Foldable f => f a -> (a -> IO b) -> IO ()
745836forConcurrently_ = flip mapConcurrently_
746837
747838-- | Perform the action in the given number of threads.
748839--
749840-- @since 2.1.1
750- replicateConcurrently :: Int -> IO a -> IO [a ]
841+ replicateConcurrently ::
842+ #ifdef DEBUG_AUTO_LABEL
843+ HasCallStack =>
844+ #endif
845+ Int -> IO a -> IO [a]
751846replicateConcurrently cnt = runConcurrently . sequenceA . replicate cnt . Concurrently
752847
753848-- | Same as 'replicateConcurrently', but ignore the results.
754849--
755850-- @since 2.1.1
756- replicateConcurrently_ :: Int -> IO a -> IO ()
851+ replicateConcurrently_ ::
852+ #ifdef DEBUG_AUTO_LABEL
853+ HasCallStack =>
854+ #endif
855+ Int -> IO a -> IO ()
757856replicateConcurrently_ cnt = runConcurrently . F. fold . replicate cnt . Concurrently . void
758857
759858-- -----------------------------------------------------------------------------
@@ -847,14 +946,18 @@ instance (Semigroup a, Monoid a) => Monoid (ConcurrentlyE e a) where
847946-- | Fork a thread that runs the supplied action, and if it raises an
848947-- exception, re-runs the action. The thread terminates only when the
849948-- action runs to completion without raising an exception.
850- forkRepeat :: IO a -> IO ThreadId
949+ forkRepeat ::
950+ #ifdef DEBUG_AUTO_LABEL
951+ HasCallStack =>
952+ #endif
953+ IO a -> IO ThreadId
851954forkRepeat action =
852955 mask $ \ restore ->
853956 let go = do r <- tryAll (restore action)
854957 case r of
855958 Left _ -> go
856959 _ -> return ()
857- in forkIO go
960+ in forkIO (debugLabelMe >> go)
858961
859962catchAll :: IO a -> (SomeException -> IO a ) -> IO a
860963catchAll = catch
@@ -866,11 +969,36 @@ tryAll = try
866969-- handler: saves a bit of time when we will be installing our own
867970-- exception handler.
868971{-# INLINE rawForkIO #-}
869- rawForkIO :: IO () -> IO ThreadId
870- rawForkIO (IO action) = IO $ \ s ->
871- case (fork# action s) of (# s1, tid # ) -> (# s1, ThreadId tid # )
972+ rawForkIO ::
973+ #ifdef DEBUG_AUTO_LABEL
974+ HasCallStack =>
975+ #endif
976+ IO () -> IO ThreadId
977+ rawForkIO action = IO $ \ s ->
978+ case (fork# action_plus s) of (# s1, tid # ) -> (# s1, ThreadId tid # )
979+ where
980+ (IO action_plus) = debugLabelMe >> action
872981
873982{-# INLINE rawForkOn #-}
874- rawForkOn :: Int -> IO () -> IO ThreadId
875- rawForkOn (I # cpu) (IO action) = IO $ \ s ->
876- case (forkOn# cpu action s) of (# s1, tid # ) -> (# s1, ThreadId tid # )
983+ rawForkOn ::
984+ #ifdef DEBUG_AUTO_LABEL
985+ HasCallStack =>
986+ #endif
987+ Int -> IO () -> IO ThreadId
988+ rawForkOn (I # cpu) action = IO $ \ s ->
989+ case (forkOn# cpu action_plus s) of (# s1, tid # ) -> (# s1, ThreadId tid # )
990+ where
991+ (IO action_plus) = debugLabelMe >> action
992+
993+
994+ debugLabelMe ::
995+ #ifdef DEBUG_AUTO_LABEL
996+ HasCallStack =>
997+ #endif
998+ IO ()
999+ debugLabelMe =
1000+ #ifdef DEBUG_AUTO_LABEL
1001+ myThreadId >>= flip labelThread (prettyCallStack callStack)
1002+ #else
1003+ pure ()
1004+ #endif
0 commit comments