Skip to content

Commit bdbd707

Browse files
committed
Refactor async handling in Database module to use IORef instead of TVar
1 parent 0f20eb4 commit bdbd707

File tree

1 file changed

+10
-18
lines changed
  • hls-graph/src/Development/IDE/Graph/Internal

1 file changed

+10
-18
lines changed

hls-graph/src/Development/IDE/Graph/Internal/Database.hs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,13 @@ module Development.IDE.Graph.Internal.Database (compute, newDatabase, incDatabas
1212

1313
import 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)
2316
import Control.Monad
24-
import Control.Monad.IO.Class (MonadIO (liftIO))
2517
import Control.Monad.Trans.Class (lift)
2618
import Control.Monad.Trans.Reader
2719
import qualified Control.Monad.Trans.State.Strict as State
2820
import Data.Dynamic
2921
import Data.Foldable (for_, traverse_)
30-
import Data.IORef.Extra
3122
import Data.Maybe
3223
import Data.Traversable (for)
3324
import Data.Tuple.Extra
@@ -40,11 +31,14 @@ import qualified Focus
4031
import qualified ListT
4132
import qualified StmContainers.Map as SMap
4233
import System.Time.Extra (duration, sleep)
43-
import UnliftIO (MonadUnliftIO (withRunInIO))
34+
import UnliftIO
4435
import qualified UnliftIO.Exception as UE
4536

4637
#if MIN_VERSION_base(4,19,0)
38+
import Control.Exception (throw)
4739
import Data.Functor (unzip)
40+
import Data.IORef.Extra (atomicModifyIORef'_)
41+
import UnliftIO.Concurrent
4842
#else
4943
import 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

286280
data 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
294288
runAIO :: Step -> AIO a -> IO a
295289
runAIO 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

319311
unliftAIO :: AIO a -> AIO (IO a)

0 commit comments

Comments
 (0)