thread-utils-context 0.3.0.1 → 0.3.0.2
raw patch · 2 files changed
+21/−20 lines, 2 files
Files
src/Control/Concurrent/Thread/Storage.hs view
@@ -55,9 +55,10 @@ import Control.Concurrent import Control.Concurrent.Thread.Finalizers-import Control.Monad ( when, void )+import Control.Monad ( when, void, forM_ ) import Control.Monad.IO.Class import Data.Maybe (isNothing, isJust)+import Data.Word (Word64) import GHC.Base (Addr#) import GHC.IO (IO(..), mask_) import GHC.Int@@ -74,24 +75,24 @@ foreign import ccall unsafe "rts_getThreadId" c_getThreadId :: Addr# -> CULLong -numStripes :: Int+numStripes :: Word numStripes = 32 -getThreadId :: ThreadId -> Int+getThreadId :: ThreadId -> Word getThreadId (ThreadId tid#) = fromIntegral (c_getThreadId (unsafeCoerce# tid#)) -stripeHash :: Int -> Int-stripeHash = (`mod` numStripes) . abs+stripeHash :: Word -> Int+stripeHash = fromIntegral . (`mod` numStripes) readStripe :: ThreadStorageMap a -> ThreadId -> IO (I.IntMap a) readStripe (ThreadStorageMap arr#) t = IO $ \s -> readArray# arr# tid# s where (I# tid#) = stripeHash $ getThreadId t -atomicModifyStripe :: ThreadStorageMap a -> Int -> (I.IntMap a -> (I.IntMap a, b)) -> IO b+atomicModifyStripe :: ThreadStorageMap a -> Word -> (I.IntMap a -> (I.IntMap a, b)) -> IO b atomicModifyStripe (ThreadStorageMap arr#) tid f = IO $ \s -> go s where- (I# stripe#) = stripeHash tid+ (I# stripe#) = fromIntegral $ stripeHash tid go s = case readArray# arr# stripe# s of (# s1, intMap #) -> let (updatedIntMap, result) = f intMap @@ -113,7 +114,7 @@ newThreadStorageMap = liftIO $ IO $ \s -> case newArray# numStripes# mempty s of (# s1, ma #) -> (# s1, ThreadStorageMap ma #) where- (I# numStripes#) = numStripes+ (I# numStripes#) = fromIntegral numStripes -- | Retrieve a value if it exists for the current thread lookup :: MonadIO m => ThreadStorageMap a -> m (Maybe a)@@ -127,7 +128,7 @@ m <- readStripe tsm tid pure $ I.lookup threadAsInt m where - threadAsInt = getThreadId tid+ threadAsInt = fromIntegral $ getThreadId tid -- | Associate the provided value with the current thread. --@@ -160,20 +161,20 @@ updateOnThread :: MonadIO m => ThreadStorageMap a -> ThreadId -> (Maybe a -> (Maybe a, b)) -> m b updateOnThread tsm tid f = liftIO $ mask_ $ do -- ^ We mask here in order to ensure that the finalizer will always be created- (isNewThreadEntry, result) <- atomicModifyStripe tsm threadAsInt $ \m -> + (isNewThreadEntry, result) <- atomicModifyStripe tsm threadAsWord $ \m -> let (resultWithNewThreadDetection, m') = I.alterF (\x -> case f x of (!x', !y) -> ((isNothing x && isJust x', y), x') ) - threadAsInt+ (fromIntegral threadAsWord) m in (m', resultWithNewThreadDetection) when isNewThreadEntry $ do- addThreadFinalizer tid $ cleanUp tsm threadAsInt+ addThreadFinalizer tid $ cleanUp tsm threadAsWord pure result where - threadAsInt = getThreadId tid+ threadAsWord = getThreadId tid update :: MonadIO m => ThreadStorageMap a -> (Maybe a -> (Maybe a, b)) -> m b update tsm f = liftIO $ do@@ -189,15 +190,15 @@ -- | Update the associated value for the specified thread if it is attached. adjustOnThread :: MonadIO m => ThreadStorageMap a -> ThreadId -> (a -> a) -> m () adjustOnThread tsm tid f = liftIO $ do- atomicModifyStripe tsm threadAsInt $ \m -> (I.adjust f threadAsInt m, ())+ atomicModifyStripe tsm threadAsWord $ \m -> (I.adjust f (fromIntegral threadAsWord) m, ()) where - threadAsInt = getThreadId tid + threadAsWord = getThreadId tid -- Remove this context for thread from the map on finalization-cleanUp :: ThreadStorageMap a -> Int -> IO ()+cleanUp :: ThreadStorageMap a -> Word -> IO () cleanUp tsm tid = do atomicModifyStripe tsm tid $ \m -> - (I.delete tid m, ())+ (I.delete (fromIntegral tid) m, ()) -- | List thread ids with live entries in the 'ThreadStorageMap'. -- @@ -206,7 +207,7 @@ -- items from being freed from a 'ThreadStorageMap' storedItems :: ThreadStorageMap a -> IO [(Int, a)] storedItems tsm = do- stripes <- mapM (stripeByIndex tsm) [0..(numStripes - 1)]+ stripes <- mapM (stripeByIndex tsm) [0..(fromIntegral numStripes - 1)] pure $ concatMap I.toList stripes where stripeByIndex :: ThreadStorageMap a -> Int -> IO (I.IntMap a)@@ -215,7 +216,7 @@ #if MIN_VERSION_base(4,18,0) -- | This should generally not be needed, but may be used to remove values prior to GC-triggered finalizers being run from the 'ThreadStorageMap' for threads that have exited. purgeDeadThreads :: MonadIO m => ThreadStorageMap a -> m ()-purgeDeadThreads tsm = do+purgeDeadThreads tsm = liftIO $ do tids <- listThreads let threadSet = IS.fromList $ map getThreadId tids forM_ [0..(numStripes - 1)] $ \stripe ->
thread-utils-context.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: thread-utils-context-version: 0.3.0.1+version: 0.3.0.2 synopsis: Garbage-collected thread local storage description: Please see the README on GitHub at <https://github.com/iand675/thread-utils-context#readme> category: Concurrency