thread-local-storage 0.1.2 → 0.2
raw patch · 5 files changed
+39/−9 lines, 5 files
Files
- CHANGELOG.md +9/−0
- Data/TLS/PThread/Internal.hs +12/−0
- bench/Main.hs +8/−7
- tests/Main.hs +2/−1
- thread-local-storage.cabal +8/−1
CHANGELOG.md view
@@ -1,3 +1,12 @@+## 0.2 [2018.07.01]+* `thread-local-storage` now checks that threads calling+ `Data.TLS.PThread.getTLS` are bound threads, and throws a runtime error if+ this is not the case.++ For this reason, if you call `getTLS` in a thread spawned by `forkOn`, it+ will break with this release, so you are encouraged to switch uses of+ `forkOn` to `forkOS`.+ ## 0.1.2 [2017.06.23] * Fix the benchmark suite with `criterion-1.2`
Data/TLS/PThread/Internal.hs view
@@ -10,6 +10,7 @@ -- with caution. module Data.TLS.PThread.Internal where +import Control.Concurrent (isCurrentThreadBound, rtsSupportsBoundThreads) import Control.Monad import Control.Exception import Data.IORef@@ -82,8 +83,14 @@ allC <- newIORef [] return $! TLS key new allC +-- | Fetches the copy of the TLS variable of the running OS thread.+--+-- The returned value is reliable only if the current thread is bound.+-- For this reason, this function calls 'error' if the current thread is+-- unbound. getTLS TLS{key,mknew,allCopies} = do p <- pthread_getspecific key+ checkBoundness if castStablePtrToPtr p == nullPtr then do a <- mknew sp <- newStablePtr a@@ -92,6 +99,11 @@ return a else deRefStablePtr p+ where+ checkBoundness = when rtsSupportsBoundThreads $ do+ b <- isCurrentThreadBound+ when (not b) $+ fail "thread-local-storage: PThread.getTLS used from an unbound thread." allTLS TLS{allCopies} = do ls <- readIORef allCopies
bench/Main.hs view
@@ -14,6 +14,7 @@ import Data.Atomics.Counter import Control.Monad+import Control.Concurrent (forkOS) import Control.Concurrent.MVar import Data.IORef import GHC.Conc@@ -86,10 +87,10 @@ -- numCapabilities. let totalIters = (fromIntegral iters) * (max numCap numT) perThread = totalIters `quot` numT- mvs <- forM [0..numT-1] $ \ n -> do+ mvs <- replicateM numT $ do v <- newEmptyMVar- _ <- forkOn n $ do rep perThread (fn x)- putMVar v ()+ _ <- forkOS $ do rep perThread (fn x)+ putMVar v () return v forM_ mvs takeMVar -- Shut down only when all threads are finished with it:@@ -101,10 +102,10 @@ -- This version uses MVar synchronization. benchPar1 :: Int -> IO () -> Benchmarkable benchPar1 num act = toBenchmarkable $ \ iters -> do- mvs <- forM [0..num-1] $ \ n -> do+ mvs <- replicateM num $ do v <- newEmptyMVar- _ <- forkOn n $ do rep (fromIntegral iters) act- putMVar v ()+ _ <- forkOS $ do rep (fromIntegral iters) act+ putMVar v () return v forM_ mvs takeMVar {-# INLINE benchPar1 #-}@@ -118,7 +119,7 @@ go = do rep (fromIntegral iters) act incrCounter_ 1 done waitCounter- forM_ [1..num-1] $ \ n -> forkOn n go+ replicateM_ (num-1) $ forkOS go go {-# INLINE benchPar2 #-}
tests/Main.hs view
@@ -7,6 +7,7 @@ import Data.IORef -- import Foreign.Ptr import GHC.Conc+import Control.Concurrent (forkOS) import Control.Concurrent.MVar import Control.Monad -- import Control.Exception@@ -33,7 +34,7 @@ tls <- mkTLS (do putStrLn " New() called.." newIORef (-1 :: Int)) mvs <- sequence $ replicate numCap newEmptyMVar- forM_ (zip [0..] mvs) $ \(ix,mv) -> forkOn ix $ do+ forM_ (zip [0..] mvs) $ \(ix,mv) -> forkOS $ do r <- getTLS tls n <- readIORef r tid <- myThreadId
thread-local-storage.cabal view
@@ -1,5 +1,5 @@ name: thread-local-storage-version: 0.1.2+version: 0.2 synopsis: Several options for thread-local-storage (TLS) in Haskell. description: .@@ -26,6 +26,13 @@ category: System build-type: Simple cabal-version: >=1.10+tested-with: GHC == 7.6.3+ , GHC == 7.8.4+ , GHC == 7.10.3+ , GHC == 8.0.2+ , GHC == 8.2.2+ , GHC == 8.4.3+ , GHC == 8.6.1 extra-source-files: CHANGELOG.md, README.md, Data/TLS/TLS_Sig.hs