@@ -12,22 +12,13 @@ module Development.IDE.Graph.Internal.Database (compute, newDatabase, incDatabas
1212
1313import Prelude hiding (unzip )
1414
15- import Control.Concurrent.Async
16- import Control.Concurrent.Extra
17- import Control.Concurrent.STM.Stats (STM , TVar , atomically ,
18- atomicallyNamed ,
19- modifyTVar' , newTVarIO ,
20- readTVar , readTVarIO ,
21- retry )
22- import Control.Exception
15+ import Control.Concurrent.STM.Stats (atomicallyNamed , retry )
2316import Control.Monad
24- import Control.Monad.IO.Class (MonadIO (liftIO ))
2517import Control.Monad.Trans.Class (lift )
2618import Control.Monad.Trans.Reader
2719import qualified Control.Monad.Trans.State.Strict as State
2820import Data.Dynamic
2921import Data.Foldable (for_ , traverse_ )
30- import Data.IORef.Extra
3122import Data.Maybe
3223import Data.Traversable (for )
3324import Data.Tuple.Extra
@@ -40,11 +31,14 @@ import qualified Focus
4031import qualified ListT
4132import qualified StmContainers.Map as SMap
4233import System.Time.Extra (duration , sleep )
43- import UnliftIO ( MonadUnliftIO ( withRunInIO ))
34+ import UnliftIO
4435import qualified UnliftIO.Exception as UE
4536
4637#if MIN_VERSION_base(4,19,0)
38+ import Control.Exception (throw )
4739import Data.Functor (unzip )
40+ import Data.IORef.Extra (atomicModifyIORef'_ )
41+ import UnliftIO.Concurrent
4842#else
4943import Data.List.NonEmpty (unzip )
5044#endif
@@ -280,7 +274,7 @@ transitiveDirtySet database = flip State.execStateT mempty . traverse_ loop
280274
281275-- | A simple monad to implement cancellation on top of 'Async',
282276-- generalizing 'withAsync' to monadic scopes.
283- newtype AIO a = AIO { unAIO :: ReaderT (TVar [Async () ]) IO a }
277+ newtype AIO a = AIO { unAIO :: ReaderT (IORef [Async () ]) IO a }
284278 deriving newtype (Applicative , Functor , Monad , MonadIO )
285279
286280data AsyncParentKill = AsyncParentKill ThreadId Step
@@ -293,14 +287,11 @@ instance Exception AsyncParentKill where
293287-- | Run the monadic computation, cancelling all the spawned asyncs if an exception arises
294288runAIO :: Step -> AIO a -> IO a
295289runAIO s (AIO act) = do
296- asyncsRef <- newTVarIO []
290+ asyncsRef <- newIORef []
297291 -- Log the exact exception (including async exceptions) before cleanup,
298292 -- then rethrow to preserve previous semantics.
299293 runReaderT act asyncsRef `onException` do
300- asyncs <- atomically $ do
301- r <- readTVar asyncsRef
302- modifyTVar' asyncsRef $ const []
303- return r
294+ asyncs <- atomicModifyIORef' asyncsRef ([] ,)
304295 tid <- myThreadId
305296 cleanupAsync asyncs tid s
306297
@@ -313,7 +304,8 @@ asyncWithCleanUp act = do
313304 -- mask to make sure we keep track of the spawned async
314305 liftIO $ uninterruptibleMask $ \ restore -> do
315306 a <- async $ restore io
316- atomically $ modifyTVar' st (void a : )
307+ -- atomically $ modifyTVar' st (void a :)
308+ atomicModifyIORef'_ st (void a: )
317309 return $ wait a
318310
319311unliftAIO :: AIO a -> AIO (IO a )
0 commit comments