Hello community,

here is the log from the commit of package ghc-unliftio for openSUSE:Factory 
checked in at 2019-01-25 22:43:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-unliftio (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-unliftio.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-unliftio"

Fri Jan 25 22:43:39 2019 rev:6 rq:667146 version:0.2.10

Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-unliftio/ghc-unliftio.changes        
2018-12-21 08:21:28.761566619 +0100
+++ /work/SRC/openSUSE:Factory/.ghc-unliftio.new.28833/ghc-unliftio.changes     
2019-01-25 22:43:39.475206564 +0100
@@ -1,0 +2,8 @@
+Mon Dec 31 03:01:33 UTC 2018 - psim...@suse.com
+
+- Update unliftio to version 0.2.10.
+  ## 0.2.10
+
+  * Add pooling related functions for unliftio
+
+-------------------------------------------------------------------

Old:
----
  unliftio-0.2.9.0.tar.gz

New:
----
  unliftio-0.2.10.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-unliftio.spec ++++++
--- /var/tmp/diff_new_pack.crOej9/_old  2019-01-25 22:43:39.963205962 +0100
+++ /var/tmp/diff_new_pack.crOej9/_new  2019-01-25 22:43:39.963205962 +0100
@@ -19,7 +19,7 @@
 %global pkg_name unliftio
 %bcond_with tests
 Name:           ghc-%{pkg_name}
-Version:        0.2.9.0
+Version:        0.2.10
 Release:        0
 Summary:        The MonadUnliftIO typeclass for unlifting monads to IO 
(batteries included)
 License:        MIT
@@ -40,6 +40,7 @@
 BuildRequires:  ghc-unliftio-core-devel
 %if %{with tests}
 BuildRequires:  ghc-QuickCheck-devel
+BuildRequires:  ghc-containers-devel
 BuildRequires:  ghc-hspec-devel
 %endif
 

++++++ unliftio-0.2.9.0.tar.gz -> unliftio-0.2.10.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unliftio-0.2.9.0/ChangeLog.md 
new/unliftio-0.2.10/ChangeLog.md
--- old/unliftio-0.2.9.0/ChangeLog.md   2018-12-11 08:12:26.000000000 +0100
+++ new/unliftio-0.2.10/ChangeLog.md    2018-12-30 13:46:30.000000000 +0100
@@ -1,5 +1,9 @@
 # Changelog for unliftio
 
+## 0.2.10
+
+* Add pooling related functions for unliftio
+
 ## 0.2.9.0
 
 * Add the new `Conc` datatype as a more efficient alternative to `Concurrently`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unliftio-0.2.9.0/README.md 
new/unliftio-0.2.10/README.md
--- old/unliftio-0.2.9.0/README.md      2018-08-27 20:11:52.000000000 +0200
+++ new/unliftio-0.2.10/README.md       2018-12-30 13:46:30.000000000 +0100
@@ -82,7 +82,7 @@
     (\h -> runReaderT (inner h) env)
 ```
 
-I dare you to try to and accomplish this with `MonadIO` and
+I dare you to try and accomplish this with `MonadIO` and
 `liftIO`. It simply can't be done. (If you're looking for the
 technical reason, it's because `IO` appears in
 [negative/argument 
position](https://www.fpcomplete.com/blog/2016/11/covariance-contravariance)
@@ -174,7 +174,7 @@
 ```haskell
 timeout :: MonadUnliftIO m => Int -> m a -> m (Maybe a)
 timeout x y = do
-  u <- askUnliftIO
+  (u :: UnliftIO m) <- askUnliftIO
   liftIO $ System.Timeout.timeout x $ unliftIO u y
 ```
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unliftio-0.2.9.0/src/UnliftIO/Async.hs 
new/unliftio-0.2.10/src/UnliftIO/Async.hs
--- old/unliftio-0.2.9.0/src/UnliftIO/Async.hs  2018-12-11 08:12:26.000000000 
+0100
+++ new/unliftio-0.2.10/src/UnliftIO/Async.hs   2018-12-30 13:46:30.000000000 
+0100
@@ -43,6 +43,20 @@
     -- ** Linking
     link, link2,
 
+    -- ** Pooled concurrency
+    pooledMapConcurrentlyN,
+    pooledMapConcurrently,
+    pooledMapConcurrentlyN_,
+    pooledMapConcurrently_,
+    pooledForConcurrentlyN,
+    pooledForConcurrently,
+    pooledForConcurrentlyN_,
+    pooledForConcurrently_,
+    pooledReplicateConcurrentlyN,
+    pooledReplicateConcurrently,
+    pooledReplicateConcurrentlyN_,
+    pooledReplicateConcurrently_,
+
     -- * Convenient utilities
     race, race_,
     concurrently, concurrently_,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unliftio-0.2.9.0/src/UnliftIO/Internals/Async.hs 
new/unliftio-0.2.10/src/UnliftIO/Internals/Async.hs
--- old/unliftio-0.2.9.0/src/UnliftIO/Internals/Async.hs        2018-12-11 
08:12:26.000000000 +0100
+++ new/unliftio-0.2.10/src/UnliftIO/Internals/Async.hs 2018-12-30 
13:46:30.000000000 +0100
@@ -1,4 +1,5 @@
 {-# LANGUAGE CPP                 #-}
+{-# LANGUAGE TupleSections       #-}
 {-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE DeriveFunctor       #-}
 {-# LANGUAGE DeriveGeneric       #-}
@@ -10,7 +11,7 @@
 module UnliftIO.Internals.Async where
 
 import           Control.Applicative
-import           Control.Concurrent       (threadDelay)
+import           Control.Concurrent       (threadDelay, getNumCapabilities)
 import qualified Control.Concurrent       as C
 import           Control.Concurrent.Async (Async)
 import qualified Control.Concurrent.Async as A
@@ -20,6 +21,7 @@
 import           Control.Monad.IO.Unlift
 import           Data.Foldable            (for_, traverse_)
 import           Data.Typeable            (Typeable)
+import           Data.IORef (IORef, readIORef, atomicWriteIORef, newIORef, 
atomicModifyIORef')
 import qualified UnliftIO.Exception       as UE
 
 -- For the implementation of Conc below, we do not want any of the
@@ -32,14 +34,10 @@
 #if MIN_VERSION_base(4,9,0)
 import           Data.Semigroup
 #else
-import           Data.Foldable            (Foldable)
 import           Data.Monoid              hiding (Alt)
-import           Data.Traversable         (Traversable)
-#endif
-
-#if MIN_VERSION_base(4,7,0)
-import           Data.Traversable         (traverse)
 #endif
+import           Data.Foldable            (Foldable, toList)
+import           Data.Traversable         (Traversable, for, traverse)
 
 -- | Unlifted 'A.async'.
 --
@@ -835,3 +833,247 @@
 
--------------------------------------------------------------------------------
 #endif
 
--------------------------------------------------------------------------------
+
+-- | Like 'mapConcurrently' from async, but instead of one thread per
+-- element, it does pooling from a set of threads. This is useful in
+-- scenarios where resource consumption is bounded and for use cases
+-- where too many concurrent tasks aren't allowed.
+--
+-- === __Example usage__
+--
+-- @
+-- import Say
+--
+-- action :: Int -> IO Int
+-- action n = do
+--   tid <- myThreadId
+--   sayString $ show tid
+--   threadDelay (2 * 10^6) -- 2 seconds
+--   return n
+--
+-- main :: IO ()
+-- main = do
+--   yx \<- pooledMapConcurrentlyN 5 (\\x -\> action x) [1..5]
+--   print yx
+-- @
+--
+-- On executing you can see that five threads have been spawned:
+--
+-- @
+-- \$ ./pool
+-- ThreadId 36
+-- ThreadId 38
+-- ThreadId 40
+-- ThreadId 42
+-- ThreadId 44
+-- [1,2,3,4,5]
+-- @
+--
+--
+-- Let's modify the above program such that there are less threads
+-- than the number of items in the list:
+--
+-- @
+-- import Say
+--
+-- action :: Int -> IO Int
+-- action n = do
+--   tid <- myThreadId
+--   sayString $ show tid
+--   threadDelay (2 * 10^6) -- 2 seconds
+--   return n
+--
+-- main :: IO ()
+-- main = do
+--   yx \<- pooledMapConcurrentlyN 3 (\\x -\> action x) [1..5]
+--   print yx
+-- @
+-- On executing you can see that only three threads are active totally:
+--
+-- @
+-- \$ ./pool
+-- ThreadId 35
+-- ThreadId 37
+-- ThreadId 39
+-- ThreadId 35
+-- ThreadId 39
+-- [1,2,3,4,5]
+-- @
+--
+-- @since 0.2.10
+pooledMapConcurrentlyN :: (MonadUnliftIO m, Traversable t)
+                      => Int -- ^ Max. number of threads. Should not be less 
than 1.
+                      -> (a -> m b) -> t a -> m (t b)
+pooledMapConcurrentlyN numProcs f xs =
+    withRunInIO $ \run -> pooledMapConcurrentlyIO numProcs (run . f) xs
+
+-- | Similar to 'pooledMapConcurrentlyN' but with number of threads
+-- set from 'getNumCapabilities'. Usually this is useful for CPU bound
+-- tasks.
+--
+-- @since 0.2.10
+pooledMapConcurrently :: (MonadUnliftIO m, Traversable t) => (a -> m b) -> t a 
-> m (t b)
+pooledMapConcurrently f xs = do
+  withRunInIO $ \run -> do
+    numProcs <- getNumCapabilities
+    pooledMapConcurrentlyIO numProcs (run . f) xs
+
+-- | Similar to 'pooledMapConcurrentlyN' but with flipped arguments.
+--
+-- @since 0.2.10
+pooledForConcurrentlyN :: (MonadUnliftIO m, Traversable t)
+                      => Int -- ^ Max. number of threads. Should not be less 
than 1.
+                      -> t a -> (a -> m b) -> m (t b)
+pooledForConcurrentlyN numProcs = flip (pooledMapConcurrentlyN numProcs)
+
+-- | Similar to 'pooledForConcurrentlyN' but with number of threads
+-- set from 'getNumCapabilities'. Usually this is useful for CPU bound
+-- tasks.
+--
+-- @since 0.2.10
+pooledForConcurrently :: (MonadUnliftIO m, Traversable t) => t a -> (a -> m b) 
-> m (t b)
+pooledForConcurrently = flip pooledMapConcurrently
+
+pooledMapConcurrentlyIO :: Traversable t => Int -> (a -> IO b) -> t a -> IO (t 
b)
+pooledMapConcurrentlyIO numProcs f xs =
+    if (numProcs < 1)
+    then error "pooledMapconcurrentlyIO: number of threads < 1"
+    else pooledMapConcurrentlyIO' numProcs f xs
+
+-- | Performs the actual pooling for the tasks. This function will
+-- continue execution until the task queue becomes empty. When one of
+-- the pooled thread finishes it's task, it will pickup the next task
+-- from the queue if an job is available.
+pooledConcurrently
+  :: Int -- ^ Max. number of threads. Should not be less than 1.
+  -> IORef [a] -- ^ Task queue. These are required as inputs for the jobs.
+  -> (a -> IO ()) -- ^ The task which will be run concurrently (but
+                 -- will be pooled properly).
+  -> IO ()
+pooledConcurrently numProcs jobsVar f = do
+  replicateConcurrently_ numProcs $ do
+    let loop = do
+          mbJob :: Maybe a <- atomicModifyIORef' jobsVar $ \x -> case x of
+            [] -> ([], Nothing)
+            var : vars -> (vars, Just var)
+          case mbJob of
+            Nothing -> return ()
+            Just x -> do
+              f x
+              loop
+     in loop
+
+pooledMapConcurrentlyIO' ::
+    Traversable t => Int  -- ^ Max. number of threads. Should not be less than 
1.
+                  -> (a -> IO b)
+                  -> t a
+                  -> IO (t b)
+pooledMapConcurrentlyIO' numProcs f xs = do
+  -- prepare one IORef per result...
+  jobs :: t (a, IORef b) <-
+    for xs (\x -> (x, ) <$> newIORef (error "pooledMapConcurrentlyIO': empty 
IORef"))
+  -- ...put all the inputs in a queue..
+  jobsVar :: IORef [(a, IORef b)] <- newIORef (toList jobs)
+  -- ...run `numProcs` threads in parallel, each
+  -- of them consuming the queue and filling in
+  -- the respective IORefs.
+  pooledConcurrently numProcs jobsVar $ \ (x, outRef) -> f x >>= 
atomicWriteIORef outRef      -- Read all the IORefs
+  for jobs (\(_, outputRef) -> readIORef outputRef)
+
+pooledMapConcurrentlyIO_' ::
+  Foldable t => Int -> (a -> IO ()) -> t a -> IO ()
+pooledMapConcurrentlyIO_' numProcs f jobs = do
+  jobsVar :: IORef [a] <- newIORef (toList jobs)
+  pooledConcurrently numProcs jobsVar f
+
+pooledMapConcurrentlyIO_ :: Foldable t => Int -> (a -> IO b) -> t a -> IO ()
+pooledMapConcurrentlyIO_ numProcs f xs =
+    if (numProcs < 1)
+    then error "pooledMapconcurrentlyIO_: number of threads < 1"
+    else pooledMapConcurrentlyIO_' numProcs (\x -> f x >> return ()) xs
+
+-- | Like 'pooledMapConcurrentlyN' but with the return value
+-- discarded.
+--
+-- @since 0.2.10
+pooledMapConcurrentlyN_ :: (MonadUnliftIO m, Foldable f)
+                        => Int -- ^ Max. number of threads. Should not be less 
than 1.
+                        -> (a -> m b) -> f a -> m ()
+pooledMapConcurrentlyN_ numProcs f t =
+  withRunInIO $ \run -> pooledMapConcurrentlyIO_ numProcs (run . f) t
+
+-- | Like 'pooledMapConcurrently' but with the return value discarded.
+--
+-- @since 0.2.10
+pooledMapConcurrently_ :: (MonadUnliftIO m, Foldable f) => (a -> m b) -> f a 
-> m ()
+pooledMapConcurrently_ f t =
+  withRunInIO $ \run -> do
+    numProcs <- getNumCapabilities
+    pooledMapConcurrentlyIO_ numProcs (run . f) t
+
+-- | Like 'pooledMapConcurrently_' but with flipped arguments.
+--
+-- @since 0.2.10
+pooledForConcurrently_ :: (MonadUnliftIO m, Foldable f) => f a -> (a -> m b) 
-> m ()
+pooledForConcurrently_ = flip pooledMapConcurrently_
+
+-- | Like 'pooledMapConcurrentlyN_' but with flipped arguments.
+--
+-- @since 0.2.10
+pooledForConcurrentlyN_ :: (MonadUnliftIO m, Foldable t)
+                        => Int -- ^ Max. number of threads. Should not be less 
than 1.
+                        -> t a -> (a -> m b) -> m ()
+pooledForConcurrentlyN_ numProcs = flip (pooledMapConcurrentlyN_ numProcs)
+
+
+-- | Pooled version of 'replicateConcurrently'. Performs the action in
+-- the pooled threads.
+--
+-- @since 0.2.10
+pooledReplicateConcurrentlyN :: (MonadUnliftIO m)
+                             => Int -- ^ Max. number of threads. Should not be 
less than 1.
+                             -> Int -- ^ Number of times to perform the action.
+                             -> m a -> m [a]
+pooledReplicateConcurrentlyN numProcs cnt task =
+    if cnt < 1
+    then return []
+    else pooledMapConcurrentlyN numProcs (\_ -> task) [1..cnt]
+
+-- | Similar to 'pooledReplicateConcurrentlyN' but with number of
+-- threads set from 'getNumCapabilities'. Usually this is useful for
+-- CPU bound tasks.
+--
+-- @since 0.2.10
+pooledReplicateConcurrently :: (MonadUnliftIO m)
+                            => Int -- ^ Number of times to perform the action.
+                            -> m a -> m [a]
+pooledReplicateConcurrently cnt task =
+    if cnt < 1
+    then return []
+    else pooledMapConcurrently (\_ -> task) [1..cnt]
+
+-- | Pooled version of 'replicateConcurrently_'. Performs the action in
+-- the pooled threads.
+--
+-- @since 0.2.10
+pooledReplicateConcurrentlyN_ :: (MonadUnliftIO m)
+                              => Int -- ^ Max. number of threads. Should not 
be less than 1.
+                              -> Int -- ^ Number of times to perform the 
action.
+                              -> m a -> m ()
+pooledReplicateConcurrentlyN_ numProcs cnt task =
+  if cnt < 1
+  then return ()
+  else pooledMapConcurrentlyN_ numProcs (\_ -> task) [1..cnt]
+
+-- | Similar to 'pooledReplicateConcurrently_' but with number of
+-- threads set from 'getNumCapabilities'. Usually this is useful for
+-- CPU bound tasks.
+--
+-- @since 0.2.10
+pooledReplicateConcurrently_ :: (MonadUnliftIO m)
+                             => Int -- ^ Number of times to perform the action.
+                             -> m a -> m ()
+pooledReplicateConcurrently_ cnt task =
+  if cnt < 1
+  then return ()
+  else pooledMapConcurrently_ (\_ -> task) [1..cnt]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unliftio-0.2.9.0/src/UnliftIO/STM.hs 
new/unliftio-0.2.10/src/UnliftIO/STM.hs
--- old/unliftio-0.2.9.0/src/UnliftIO/STM.hs    2018-12-11 08:12:26.000000000 
+0100
+++ new/unliftio-0.2.10/src/UnliftIO/STM.hs     2018-12-30 13:46:30.000000000 
+0100
@@ -84,7 +84,6 @@
 import qualified Control.Concurrent.STM as STM
 import Control.Monad.IO.Unlift
 import System.Mem.Weak (Weak)
-
 #if MIN_VERSION_base(4, 8, 0)
 import GHC.Natural (Natural)
 #else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unliftio-0.2.9.0/test/UnliftIO/PooledAsyncSpec.hs 
new/unliftio-0.2.10/test/UnliftIO/PooledAsyncSpec.hs
--- old/unliftio-0.2.9.0/test/UnliftIO/PooledAsyncSpec.hs       1970-01-01 
01:00:00.000000000 +0100
+++ new/unliftio-0.2.10/test/UnliftIO/PooledAsyncSpec.hs        2018-12-30 
13:46:30.000000000 +0100
@@ -0,0 +1,203 @@
+{-#LANGUAGE DeriveDataTypeable#-}
+{-#LANGUAGE BangPatterns#-}
+
+module UnliftIO.PooledAsyncSpec (spec) where
+
+import Test.Hspec
+import Control.Concurrent
+import Data.List (sort)
+import Test.QuickCheck
+import qualified Data.Set as Set
+import Data.Functor ((<$>))
+import UnliftIO
+
+data MyPooledException = PoolHellException
+                         deriving (Show, Typeable)
+
+instance Exception MyPooledException
+
+-- | Strip out duplicates. (Taken from rio)
+nubOrd :: Ord a => [a] -> [a]
+nubOrd =
+  loop Set.empty
+  where
+    loop _ [] = []
+    loop !s (a:as)
+      | a `Set.member` s = loop s as
+      | otherwise = a : loop (Set.insert a s) as
+
+spec :: Spec
+spec = do
+  let exAction :: Int -> IO Int
+      exAction x = do
+        if (x == 2) then throwIO PoolHellException else return ()
+        return x
+
+      action :: Int -> IO ThreadId
+      action x = do
+         threadDelay (2 * 10^5)
+         myThreadId
+
+      myVar :: IO (TVar Int)
+      myVar = atomically $ newTVar 0
+
+      maxTVar :: Int -> TVar Int -> IO ()
+      maxTVar cval tvar = do
+         atomically $ do
+           v <- readTVar tvar
+           if cval >= v
+           then writeTVar tvar cval
+           else return ()
+
+      poolException :: Selector MyPooledException
+      poolException = const True
+
+  describe "pooled mapConcurrencyN" $ do
+    it "Throws exception properly" $ do
+       (pooledMapConcurrentlyN 5 exAction [1..5]) `shouldThrow` poolException
+
+    it "total thread should be >= 1" $ do
+       (pooledMapConcurrentlyN 0 action [1..5]) `shouldThrow` anyErrorCall
+
+    it "should not spawn more than five threads for five concurrent tasks" $ do
+       xs <- (pooledMapConcurrentlyN 5 action [1..5])
+       (length $ nubOrd xs) `shouldSatisfy` (<= (5 :: Int))
+
+    it "should not spawn more than three threads for five concurrent tasks" $ 
do
+       xs <- (pooledMapConcurrentlyN 3 action [1..5])
+       (length $ nubOrd xs) `shouldSatisfy` (<= (3 :: Int))
+
+    it "should spawn only one thread" $ do
+       xs <- (pooledMapConcurrentlyN 1 action [1..5])
+       (length $ nubOrd xs) `shouldBe` 1
+
+    it "never uses more than the given number of pools and doesn't miss any 
return values" $
+        forAllShrink ((+ 1) . abs <$> arbitrary) (filter (>= 1) . shrink) $ 
\threads ->
+            property $ \list -> do
+                threadIdsVar <- newTVarIO []
+                let go :: Int -> IO Int
+                    go i = do
+                        tid <- myThreadId
+                        atomically $ modifyTVar threadIdsVar (tid :)
+                        return i
+                list' <- pooledMapConcurrentlyN threads go list
+                sort list' `shouldBe` sort list
+                tids <- readTVarIO threadIdsVar
+                length (nubOrd tids) `shouldSatisfy` (<= threads)
+
+  describe "pooled mapConcurrencyN_" $ do
+    it "Throws exception properly" $ do
+       (pooledMapConcurrentlyN_ 5 exAction [1..5]) `shouldThrow` poolException
+
+    it "total thread should be >= 1" $ do
+       (pooledMapConcurrentlyN_ 0 action [1..5]) `shouldThrow` anyErrorCall
+
+    it "find proper maximum value" $ do
+       var <- myVar
+       xs <- (pooledMapConcurrentlyN_ 5 (\x -> maxTVar x var) [1..5])
+       newVar <- atomically $ readTVar var
+       atomically $ writeTVar var 0
+       newVar `shouldBe` 5
+
+    it "find proper maximum value with 2 threads" $ do
+       var <- myVar
+       xs <- (pooledMapConcurrentlyN_ 2 (\x -> maxTVar x var) [1..5])
+       newVar <- atomically $ readTVar var
+       atomically $ writeTVar var 0
+       newVar `shouldBe` 5
+
+    it "find proper maximum value with 1 threads" $ do
+       var <- myVar
+       xs <- (pooledMapConcurrentlyN_ 1 (\x -> maxTVar x var) [1..5])
+       newVar <- atomically $ readTVar var
+       atomically $ writeTVar var 0
+       newVar `shouldBe` 5
+
+    it "make sure activity is happening in different threads" $ do
+       let myThreads :: IO (TVar [ThreadId])
+           myThreads = atomically $ newTVar []
+
+           collectThreads :: TVar [ThreadId] -> IO ()
+           collectThreads threadVar = do
+             tid <- myThreadId
+             atomically $ do
+               tvar <- readTVar threadVar
+               writeTVar threadVar (tid:tvar)
+             threadDelay $ 2 * 10^5
+
+       tid <- myThreads
+       xs <- pooledMapConcurrentlyN_ 5 (\_ -> collectThreads tid) [1..5]
+       tids <- atomically $ readTVar tid
+       (length $ nubOrd tids) `shouldSatisfy` (<= 5)
+
+    it "Not more than 5 threads will be spawned even if pooling is set to 8 " 
$ do
+       let myThreads :: IO (TVar [ThreadId])
+           myThreads = atomically $ newTVar []
+
+           collectThreads :: TVar [ThreadId] -> IO ()
+           collectThreads threadVar = do
+             tid <- myThreadId
+             atomically $ do
+               tvar <- readTVar threadVar
+               writeTVar threadVar (tid:tvar)
+             threadDelay $ 2 * 10^5
+
+       tid <- myThreads
+       xs <- pooledMapConcurrentlyN_ 8 (\_ -> collectThreads tid) [1..5]
+       tids <- atomically $ readTVar tid
+       (length $ nubOrd tids) `shouldSatisfy` (<= 5)
+
+  describe "replicate concurrencyN" $ do
+    it "Throws exception properly" $ do
+       (pooledReplicateConcurrentlyN 5 1 (exAction 2)) `shouldThrow` 
poolException
+
+    it "total thread should be >= 1" $ do
+       (pooledReplicateConcurrentlyN 0 1 (action 1)) `shouldThrow` anyErrorCall
+
+    it "Read tvar value should be 100" $ do
+       var <- myVar
+       xs <- (pooledReplicateConcurrentlyN 5 5 (maxTVar 100 var))
+       newVar <- atomically $ readTVar var
+       atomically $ writeTVar var 0
+       newVar `shouldBe` 100
+
+    it "should not spawn more than five threads for five concurrent tasks" $ do
+       xs <- (pooledReplicateConcurrentlyN 5 5 (action 1))
+       (length $ nubOrd xs) `shouldSatisfy` (<= (5 :: Int))
+
+    it "should not spawn more than three threads for five concurrent tasks" $ 
do
+       xs <- (pooledReplicateConcurrentlyN 3 5 (action 1))
+       (length $ nubOrd xs) `shouldSatisfy` (<= (3 :: Int))
+
+    it "should spawn only one thread" $ do
+       xs <- (pooledReplicateConcurrentlyN 1 5 (action 1))
+       (length $ nubOrd xs) `shouldBe` 1
+
+    it "should give empty list" $ do
+       xs <- (pooledReplicateConcurrentlyN 3 0 (action 1))
+       xs `shouldBe` []
+
+    it "should give empty list for -ve count" $ do
+       xs <- (pooledReplicateConcurrentlyN 3 (-3) (action 1))
+       xs `shouldBe` []
+
+  describe "pooled replicateConcurrencyN_" $ do
+    it "Throws exception properly" $ do
+       (pooledReplicateConcurrentlyN_ 5 1 (exAction 2)) `shouldThrow` 
poolException
+
+    it "total thread should be >= 1" $ do
+       (pooledReplicateConcurrentlyN_ 0 2 (action 1)) `shouldThrow` 
anyErrorCall
+
+    it "find proper maximum value" $ do
+       var <- myVar
+       pooledReplicateConcurrentlyN_ 5 3 (maxTVar 200 var)
+       newVar <- atomically $ readTVar var
+       atomically $ writeTVar var 0
+       newVar `shouldBe` 200
+
+    it "Should be initial value" $ do
+       var <- myVar
+       pooledReplicateConcurrentlyN_ 5 (-2) (maxTVar 200 var)
+       newVar <- atomically $ readTVar var
+       atomically $ writeTVar var 0
+       newVar `shouldBe` 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unliftio-0.2.9.0/unliftio.cabal 
new/unliftio-0.2.10/unliftio.cabal
--- old/unliftio-0.2.9.0/unliftio.cabal 2018-12-11 08:12:38.000000000 +0100
+++ new/unliftio-0.2.10/unliftio.cabal  2018-12-30 13:51:55.000000000 +0100
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.30.0.
+-- This file has been generated from package.yaml by hpack version 0.31.1.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 6ffa5ab703752662320163d252f2b4f425c0b85a390c41b8c9e74b15fbf93936
+-- hash: 806905923ede98dbf20fe24ac95d14b92b4a62626183173c24b86850dc5beada
 
 name:           unliftio
-version:        0.2.9.0
+version:        0.2.10
 synopsis:       The MonadUnliftIO typeclass for unlifting monads to IO 
(batteries included)
 description:    Please see the documentation and README at 
<https://www.stackage.org/package/unliftio>
 category:       Control
@@ -86,6 +86,7 @@
       QuickCheck
     , async >2.1.1
     , base >=4.7 && <5
+    , containers
     , deepseq
     , directory
     , filepath
@@ -106,6 +107,7 @@
       UnliftIO.ExceptionSpec
       UnliftIO.IOSpec
       UnliftIO.MemoizeSpec
+      UnliftIO.PooledAsyncSpec
       Paths_unliftio
   default-language: Haskell2010
 


Reply via email to