diff --git a/Control/Concurrent/Classy/Async.hs b/Control/Concurrent/Classy/Async.hs
--- a/Control/Concurrent/Classy/Async.hs
+++ b/Control/Concurrent/Classy/Async.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP        #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE RankNTypes #-}
 
 -- | This module is a version of the
@@ -47,6 +47,7 @@
   , poll, pollSTM
   , waitCatch, waitCatchSTM
   , cancel
+  , uninterruptibleCancel
   , cancelWith
   , asyncThreadId
 
@@ -69,9 +70,10 @@
   -- * Convenient utilities
   , race
   , race_
-  , concurrently
-  , mapConcurrently
-  , forConcurrently
+  , concurrently, concurrently_
+  , mapConcurrently, mapConcurrently_
+  , forConcurrently, forConcurrently_
+  , replicateConcurrently, replicateConcurrently_
   , Concurrently(..)
   ) where
 
@@ -82,9 +84,11 @@
 import Control.Monad.Catch (finally, try, onException)
 import Control.Monad.Conc.Class
 import Control.Monad.STM.Class
-
-#if !MIN_VERSION_base(4,8,0)
+import Data.Foldable (foldMap)
 import Data.Traversable
+
+#if MIN_VERSION_base(4,9,0)
+import Data.Semigroup (Semigroup(..))
 #endif
 
 -----------------------------------------------------------------------------------------
@@ -98,14 +102,18 @@
 -- Note that, unlike the \"async\" package, 'Async' here does not have
 -- an 'Ord' instance. This is because 'MonadConc' 'ThreadId's do not
 -- necessarily have one.
+--
+-- @since 1.1.1.0
 data Async m a = Async
   { asyncThreadId :: !(ThreadId m)
   , _asyncWait :: STM m (Either SomeException a)
   }
 
+-- | @since 1.1.1.0
 instance MonadConc m => Eq (Async m a) where
   Async t1 _ == Async t2 _ = t1 == t2
 
+-- | @since 1.1.1.0
 instance MonadConc m => Functor (Async m) where
   fmap f (Async t w) = Async t $ fmap f <$> w
 
@@ -124,40 +132,65 @@
 -- >   <$> Concurrently (getURL "url1")
 -- >   <*> Concurrently (getURL "url2")
 -- >   <*> Concurrently (getURL "url3")
+--
+-- @since 1.1.1.0
 newtype Concurrently m a = Concurrently { runConcurrently :: m a }
 
+-- | @since 1.1.1.0
 instance MonadConc m => Functor (Concurrently m) where
   fmap f (Concurrently a) = Concurrently $ f <$> a
 
+-- | @since 1.1.1.0
 instance MonadConc m => Applicative (Concurrently m) where
   pure = Concurrently . return
 
   Concurrently fs <*> Concurrently as =
     Concurrently $ (\(f, a) -> f a) <$> concurrently fs as
 
+-- | @since 1.1.1.0
 instance MonadConc m => Alternative (Concurrently m) where
   empty = Concurrently $ forever yield
 
   Concurrently as <|> Concurrently bs =
     Concurrently $ either id id <$> race as bs
 
+#if MIN_VERSION_base(4,9,0)
+-- | Only defined for base >= 4.9.0.0
+--
+-- @since 1.1.2.0
+instance (MonadConc m, Semigroup a) => Semigroup (Concurrently m a) where
+  (<>) = liftA2 (<>)
+#endif
 
+-- | @since 1.1.2.0
+instance (MonadConc m, Monoid a) => Monoid (Concurrently m a) where
+  mempty = pure mempty
+  mappend = liftA2 mappend
+
 -------------------------------------------------------------------------------
 -- Spawning
 
 -- | Spawn an asynchronous action in a separate thread.
+--
+-- @since 1.1.1.0
 async :: MonadConc m => m a -> m (Async m a)
 async = asyncUsing fork
 
 -- | Like 'async' but using 'forkOn' internally.
+--
+-- @since 1.1.1.0
 asyncOn :: MonadConc m => Int -> m a -> m (Async m a)
 asyncOn = asyncUsing . forkOn
 
 -- | Like 'async' but using 'forkWithUnmask' internally.
+--
+-- @since 1.1.1.0
 asyncWithUnmask :: MonadConc m => ((forall b. m b -> m b) -> m a) -> m (Async m a)
 asyncWithUnmask = asyncUnmaskUsing forkWithUnmask
 
 -- | Like 'asyncOn' but using 'forkOnWithUnmask' internally.
+--
+-- @since 1.1.1.0
 asyncOnWithUnmask :: MonadConc m => Int -> ((forall b. m b -> m b) -> m a) -> m (Async m a)
 asyncOnWithUnmask i = asyncUnmaskUsing (forkOnWithUnmask i)
 
@@ -180,27 +213,35 @@
 
 -- | Spawn an asynchronous action in a separate thread, and pass its
 -- @Async@ handle to the supplied function. When the function returns
--- or throws an exception, 'cancel' is called on the @Async@.
+-- or throws an exception, 'uninterruptibleCancel' is called on the @Async@.
 --
--- > withAsync action inner = bracket (async action) cancel inner
+-- > withAsync action inner = bracket (async action) uninterruptiblCancel inner
 --
 -- This is a useful variant of 'async' that ensures an @Async@ is
 -- never left running unintentionally.
 --
--- Since 'cancel' may block, 'withAsync' may also block; see 'cancel'
--- for details.
+-- Since 'uninterruptibleCancel' may block, 'withAsync' may also
+-- block; see 'uninterruptibleCancel' for details.
+--
+-- @since 1.1.1.0
 withAsync :: MonadConc m => m a -> (Async m a -> m b) -> m b
 withAsync = withAsyncUsing fork
 
 -- | Like 'withAsync' but uses 'forkOn' internally.
+--
+-- @since 1.1.1.0
 withAsyncOn :: MonadConc m => Int -> m a -> (Async m a -> m b) -> m b
 withAsyncOn = withAsyncUsing . forkOn
 
 -- | Like 'withAsync' bit uses 'forkWithUnmask' internally.
+--
+-- @since 1.1.1.0
 withAsyncWithUnmask :: MonadConc m => ((forall x. m x -> m x) -> m a) -> (Async m a -> m b) -> m b
 withAsyncWithUnmask = withAsyncUnmaskUsing forkWithUnmask
 
 -- | Like 'withAsyncOn' bit uses 'forkOnWithUnmask' internally.
+--
+-- @since 1.1.1.0
 withAsyncOnWithUnmask :: MonadConc m => Int -> ((forall x. m x -> m x) -> m a) -> (Async m a -> m b) -> m b
 withAsyncOnWithUnmask i = withAsyncUnmaskUsing (forkOnWithUnmask i)
 
@@ -216,7 +257,7 @@
 
   let a = Async tid (readTMVar var)
 
-  res <- inner a `catchAll` (\e -> cancel a >> throw e)
+  res <- inner a `catchAll` (\e -> uninterruptibleCancel a >> throw e)
   cancel a
 
   return res
@@ -230,7 +271,7 @@
 
   let a = Async tid (readTMVar var)
 
-  res <- inner a `catchAll` (\e -> cancel a >> throw e)
+  res <- inner a `catchAll` (\e -> uninterruptibleCancel a >> throw e)
   cancel a
 
   return res
@@ -246,10 +287,14 @@
 -- exception is re-thrown by 'wait'.
 --
 -- > wait = atomically . waitSTM
+--
+-- @since 1.1.1.0
 wait :: MonadConc m => Async m a -> m a
 wait = atomically . waitSTM
 
 -- | A version of 'wait' that can be used inside a @MonadSTM@ transaction.
+--
+-- @since 1.1.1.0
 waitSTM :: MonadConc m => Async m a -> STM m a
 waitSTM a = do
  r <- waitCatchSTM a
@@ -261,39 +306,59 @@
 -- exception @x@, or @Right a@ if it returned a value @a@.
 --
 -- > poll = atomically . pollSTM
+--
+-- @since 1.1.1.0
 poll :: MonadConc m => Async m a -> m (Maybe (Either SomeException a))
 poll = atomically . pollSTM
 
 -- | A version of 'poll' that can be used inside a @MonadSTM@ transaction.
+--
+-- @since 1.1.1.0
 pollSTM :: MonadConc m => Async m a -> STM m (Maybe (Either SomeException a))
 pollSTM (Async _ w) = (Just <$> w) `orElse` return Nothing
 
 -- | Wait for an asynchronous action to complete, and return either
 -- @Left e@ if the action raised an exception @e@, or @Right a@ if it
 -- returned a value @a@.
+--
+-- @since 1.1.1.0
 waitCatch :: MonadConc m => Async m a -> m (Either SomeException a)
 waitCatch = tryAgain . atomically . waitCatchSTM where
   -- See: https://github.com/simonmar/async/issues/14
   tryAgain f = f `catch` \BlockedIndefinitelyOnSTM -> f
 
 -- | A version of 'waitCatch' that can be used inside a @MonadSTM@ transaction.
+--
+-- @since 1.1.1.0
 waitCatchSTM :: MonadConc m => Async m a -> STM m (Either SomeException a)
 waitCatchSTM (Async _ w) = w
 
 -- | Cancel an asynchronous action by throwing the @ThreadKilled@
--- exception to it. Has no effect if the 'Async' has already
--- completed.
+-- exception to it, and waiting for the 'Async' thread to quit. Has no
+-- effect if the 'Async' has already completed.
 --
--- > cancel a = throwTo (asyncThreadId a) ThreadKilled
+-- > cancel a = throwTo (asyncThreadId a) ThreadKilled <* waitCatch a
 --
--- Note that 'cancel' is synchronous in the same sense as 'throwTo'.
--- It does not return until the exception has been thrown in the
--- target thread, or the target thread has completed. An asynchronous
--- 'cancel' can of course be obtained by wrapping 'cancel' itself in
--- 'async'.
+-- Note that 'cancel' will not terminate until the thread the 'Async'
+-- refers to has terminated. This means that 'cancel' will block for
+-- as long as said thread blocks when receiving an asynchronous
+-- exception.
+--
+-- An asynchronous 'cancel' can of course be obtained by wrapping
+-- 'cancel' itself in 'async'.
+--
+-- @since 1.1.1.0
 cancel :: MonadConc m => Async m a -> m ()
-cancel (Async tid _) = throwTo tid ThreadKilled
+cancel a@(Async tid _) = throwTo tid ThreadKilled <* waitCatch a
 
+-- | Cancel an asynchronous action.
+--
+-- This is a variant of 'cancel' but it is not interruptible.
+--
+-- @since 1.1.2.0
+uninterruptibleCancel :: MonadConc m => Async m a -> m ()
+uninterruptibleCancel = uninterruptibleMask_ . cancel
+
 -- | Cancel an asynchronous action by throwing the supplied exception
 -- to it.
 --
@@ -301,6 +366,8 @@
 --
 -- The notes about the synchronous nature of 'cancel' also apply to
 -- 'cancelWith'.
+--
+-- @since 1.1.1.0
 cancelWith :: (MonadConc m, Exception e) => Async m a -> e -> m ()
 cancelWith (Async tid _) = throwTo tid
 
@@ -314,11 +381,15 @@
 --
 -- If multiple 'Async's complete or have completed, then the value
 -- returned corresponds to the first completed 'Async' in the list.
+--
+-- @since 1.1.1.0
 waitAny :: MonadConc m => [Async m a] -> m (Async m a, a)
 waitAny = atomically . waitAnySTM
 
 -- | A version of 'waitAny' that can be used inside a @MonadSTM@
 -- transaction.
+--
+-- @since 1.1.1.0
 waitAnySTM :: MonadConc m => [Async m a] -> STM m (Async m a, a)
 waitAnySTM = foldr (orElse . (\a -> do r <- waitSTM a; return (a, r))) retry
 
@@ -328,43 +399,59 @@
 --
 -- If multiple 'Async's complete or have completed, then the value
 -- returned corresponds to the first completed 'Async' in the list.
+--
+-- @since 1.1.1.0
 waitAnyCatch :: MonadConc m => [Async m a] -> m (Async m a, Either SomeException a)
 waitAnyCatch = atomically . waitAnyCatchSTM
 
 -- | A version of 'waitAnyCatch' that can be used inside a @MonadSTM@
 -- transaction.
+--
+-- @since 1.1.1.0
 waitAnyCatchSTM :: MonadConc m => [Async m a] -> STM m (Async m a, Either SomeException a)
 waitAnyCatchSTM = foldr (orElse . (\a -> do r <- waitCatchSTM a; return (a, r))) retry
 
 -- | Like 'waitAny', but also cancels the other asynchronous
 -- operations as soon as one has completed.
+--
+-- @since 1.1.1.0
 waitAnyCancel :: MonadConc m => [Async m a] -> m (Async m a, a)
 waitAnyCancel asyncs = waitAny asyncs `finally` mapM_ cancel asyncs
 
 -- | Like 'waitAnyCatch', but also cancels the other asynchronous
 -- operations as soon as one has completed.
+--
+-- @since 1.1.1.0
 waitAnyCatchCancel :: MonadConc m => [Async m a] -> m (Async m a, Either SomeException a)
 waitAnyCatchCancel asyncs = waitAnyCatch asyncs `finally` mapM_ cancel asyncs
 
 -- | Wait for the first of two @Async@s to finish.  If the @Async@
 -- that finished first raised an exception, then the exception is
 -- re-thrown by 'waitEither'.
+--
+-- @since 1.1.1.0
 waitEither :: MonadConc m => Async m a -> Async m b -> m (Either a b)
 waitEither left right = atomically $ waitEitherSTM left right
 
 -- | A version of 'waitEither' that can be used inside a @MonadSTM@
 -- transaction.
+--
+-- @since 1.1.1.0
 waitEitherSTM :: MonadConc m => Async m a -> Async m b -> STM m (Either a b)
 waitEitherSTM left right =
   (Left <$> waitSTM left) `orElse` (Right <$> waitSTM right)
 
 -- | Wait for the first of two @Async@s to finish.
+--
+-- @since 1.1.1.0
 waitEitherCatch :: MonadConc m => Async m a -> Async m b
   -> m (Either (Either SomeException a) (Either SomeException b))
 waitEitherCatch left right = atomically $ waitEitherCatchSTM left right
 
 -- | A version of 'waitEitherCatch' that can be used inside a
 -- @MonadSTM@ transaction.
+--
+-- @since 1.1.1.0
 waitEitherCatchSTM :: MonadConc m => Async m a -> Async m b
   -> STM m (Either (Either SomeException a) (Either SomeException b))
 waitEitherCatchSTM left right =
@@ -372,34 +459,46 @@
 
 -- | Like 'waitEither', but also 'cancel's both @Async@s before
 -- returning.
+--
+-- @since 1.1.1.0
 waitEitherCancel :: MonadConc m => Async m a -> Async m b -> m (Either a b)
 waitEitherCancel left right =
   waitEither left right `finally` (cancel left >> cancel right)
 
 -- | Like 'waitEitherCatch', but also 'cancel's both @Async@s before
 -- returning.
+--
+-- @since 1.1.1.0
 waitEitherCatchCancel :: MonadConc m => Async m a -> Async m b
   -> m (Either (Either SomeException a) (Either SomeException b))
 waitEitherCatchCancel left right =
   waitEitherCatch left right `finally` (cancel left >> cancel right)
 
 -- | Like 'waitEither', but the result is ignored.
+--
+-- @since 1.1.1.0
 waitEither_ :: MonadConc m => Async m a -> Async m b -> m ()
 waitEither_ left right = atomically $ waitEitherSTM_ left right
 
 -- | A version of 'waitEither_' that can be used inside a @MonadSTM@
 -- transaction.
+--
+-- @since 1.1.1.0
 waitEitherSTM_:: MonadConc m => Async m a -> Async m b -> STM m ()
 waitEitherSTM_ left right = void $ waitEitherSTM left right
 
 -- | Waits for both @Async@s to finish, but if either of them throws
 -- an exception before they have both finished, then the exception is
 -- re-thrown by 'waitBoth'.
+--
+-- @since 1.1.1.0
 waitBoth :: MonadConc m => Async m a -> Async m b -> m (a, b)
 waitBoth left right = atomically $ waitBothSTM left right
 
 -- | A version of 'waitBoth' that can be used inside a @MonadSTM@
 -- transaction.
+--
+-- @since 1.1.1.0
 waitBothSTM :: MonadConc m => Async m a -> Async m b -> STM m (a, b)
 waitBothSTM left right = do
   a <- waitSTM left `orElse` (waitSTM right >> retry)
@@ -414,6 +513,7 @@
 -- @Async@ raises an exception, that exception will be re-thrown in
 -- the current thread.
 --
+-- @since 1.1.1.0
 link :: MonadConc m => Async m a -> m ()
 link (Async _ w) = do
   me <- myThreadId
@@ -425,6 +525,8 @@
 
 -- | Link two @Async@s together, such that if either raises an
 -- exception, the same exception is re-thrown in the other @Async@.
+--
+-- @since 1.1.1.0
 link2 :: MonadConc m => Async m a -> Async m b -> m ()
 link2 left@(Async tl _)  right@(Async tr _) =
   void $ forkRepeat $ do
@@ -458,6 +560,7 @@
 -- >   withAsync right $ \b ->
 -- >   waitEither a b
 --
+-- @since 1.1.1.0
 race :: MonadConc m => m a -> m b -> m (Either a b)
 race left right = concurrently' left right collect where
   collect m = do
@@ -472,6 +575,8 @@
 -- >   withAsync left $ \a ->
 -- >   withAsync right $ \b ->
 -- >   waitEither_ a b
+--
+-- @since 1.1.1.0
 race_ :: MonadConc m => m a -> m b -> m ()
 race_ a b = void $ race a b
 
@@ -484,6 +589,8 @@
 -- >   withAsync left $ \a ->
 -- >   withAsync right $ \b ->
 -- >   waitBoth a b
+--
+-- @since 1.1.1.0
 concurrently :: MonadConc m => m a -> m b -> m (a, b)
 concurrently left right = concurrently' left right (collect []) where
   collect [Left a, Right b] _ = return (a, b)
@@ -494,6 +601,18 @@
       Left ex -> throw ex
       Right r -> collect (r:xs) m
 
+-- | 'concurrently_' is 'concurrently' but ignores the return values.
+--
+-- @since 1.1.2.0
+concurrently_ :: MonadConc m => m a -> m b -> m ()
+concurrently_ left right = concurrently' left right (collect 0) where
+  collect 2 _ = pure ()
+  collect i m = do
+    e <- takeMVar m
+    case e of
+      Left ex -> throw ex
+      Right _ -> collect (i+1::Int) m
+
 -- Run two things concurrently. Faster than the 'Async' version.
 concurrently' :: MonadConc m => m a -> m b
   -> (MVar m (Either SomeException (Either a b)) -> m r)
@@ -525,6 +644,7 @@
 --
 -- > pages <- mapConcurrently getURL ["url1", "url2", "url3"]
 --
+-- @since 1.1.1.0
 mapConcurrently :: (Traversable t, MonadConc m) => (a -> m b) -> t a -> m (t b)
 mapConcurrently f = runConcurrently . traverse (Concurrently . f)
 
@@ -532,5 +652,33 @@
 --
 -- > pages <- forConcurrently ["url1", "url2", "url3"] $ \url -> getURL url
 --
+-- @since 1.1.1.0
 forConcurrently :: (Traversable t, MonadConc m) => t a -> (a -> m b)-> m (t b)
 forConcurrently = flip mapConcurrently
+
+-- | 'mapConcurrently_' is 'mapConcurrently' with the return value
+-- discarded, just like 'mapM_'.
+--
+-- @since 1.1.2.0
+mapConcurrently_ :: (Foldable f, MonadConc m) => (a -> m b) -> f a -> m ()
+mapConcurrently_ f = runConcurrently . foldMap (Concurrently . void . f)
+
+-- | 'forConcurrently_' is 'forConcurrently' with the return value
+-- discarded, just like 'forM_'.
+--
+-- @since 1.1.2.0
+forConcurrently_ :: (Foldable f, MonadConc m) => f a -> (a -> m b) -> m ()
+forConcurrently_ = flip mapConcurrently_
+
+-- | Perform the action in the given number of threads.
+--
+-- @since 1.1.2.0
+replicateConcurrently :: MonadConc m => Int -> m a -> m [a]
+replicateConcurrently i = runConcurrently . sequenceA . replicate i . Concurrently
+
+-- | 'replicateConcurrently_' is 'replicateConcurrently' with the
+-- return values discarded.
+--
+-- @since 1.1.2.0
+replicateConcurrently_ :: MonadConc m => Int -> m a -> m ()
+replicateConcurrently_ i = void . replicateConcurrently i
diff --git a/Control/Concurrent/Classy/CRef.hs b/Control/Concurrent/Classy/CRef.hs
--- a/Control/Concurrent/Classy/CRef.hs
+++ b/Control/Concurrent/Classy/CRef.hs
@@ -96,10 +96,14 @@
 -- >readCRef ref >>= print
 --
 -- To avoid this problem, use 'modifyCRef'' instead.
+--
+-- @since 1.0.0.0
 modifyCRef :: MonadConc m => CRef m a -> (a -> a) -> m ()
 modifyCRef ref f = readCRef ref >>= writeCRef ref . f
 
 -- | Strict version of 'modifyCRef'
+--
+-- @since 1.0.0.0
 modifyCRef' :: MonadConc m => CRef m a -> (a -> a) -> m ()
 modifyCRef' ref f = do
   x <- readCRef ref
@@ -107,6 +111,8 @@
 
 -- | Strict version of 'atomicModifyCRef'. This forces both the value
 -- stored in the @CRef@ as well as the value returned.
+--
+-- @since 1.0.0.0
 atomicModifyCRef' :: MonadConc m => CRef m a -> (a -> (a,b)) -> m b
 atomicModifyCRef' ref f = do
   b <- atomicModifyCRef ref $ \a -> case f a of
diff --git a/Control/Concurrent/Classy/Chan.hs b/Control/Concurrent/Classy/Chan.hs
--- a/Control/Concurrent/Classy/Chan.hs
+++ b/Control/Concurrent/Classy/Chan.hs
@@ -33,6 +33,8 @@
 
 -- | 'Chan' is an abstract type representing an unbounded FIFO
 -- channel.
+--
+-- @since 1.0.0.0
 data Chan m a
   = Chan (MVar m (Stream m a))
          (MVar m (Stream m a)) -- Invariant: the Stream a is always an empty MVar
@@ -42,6 +44,8 @@
 data ChItem m a = ChItem a (Stream m a)
 
 -- | Build and returns a new instance of 'Chan'.
+--
+-- @since 1.0.0.0
 newChan :: MonadConc m => m (Chan m a)
 newChan = do
   hole  <- newEmptyMVar
@@ -50,6 +54,8 @@
   pure (Chan readVar writeVar)
 
 -- | Write a value to a 'Chan'.
+--
+-- @since 1.0.0.0
 writeChan :: MonadConc m => Chan m a -> a -> m ()
 writeChan (Chan _ writeVar) val = do
   new_hole <- newEmptyMVar
@@ -59,6 +65,8 @@
     putMVar writeVar new_hole
 
 -- | Read the next value from the 'Chan'.
+--
+-- @since 1.0.0.0
 readChan :: MonadConc m => Chan m a -> m a
 readChan (Chan readVar _) =  modifyMVarMasked readVar $ \read_end -> do
   (ChItem val new_read_end) <- readMVar read_end
@@ -68,6 +76,8 @@
 -- written to either channel from then on will be available from both.
 -- Hence this creates a kind of broadcast channel, where data written
 -- by anyone is seen by everyone else.
+--
+-- @since 1.0.0.0
 dupChan :: MonadConc m => Chan m a -> m (Chan m a)
 dupChan (Chan _ writeVar) = do
   hole       <- readMVar writeVar
@@ -75,5 +85,7 @@
   pure (Chan newReadVar writeVar)
 
 -- | Write an entire list of items to a 'Chan'.
+--
+-- @since 1.0.0.0
 writeList2Chan :: MonadConc m => Chan m a -> [a] -> m ()
 writeList2Chan = mapM_ . writeChan
diff --git a/Control/Concurrent/Classy/MVar.hs b/Control/Concurrent/Classy/MVar.hs
--- a/Control/Concurrent/Classy/MVar.hs
+++ b/Control/Concurrent/Classy/MVar.hs
@@ -54,6 +54,8 @@
 -- | Swap the contents of a @MVar@, and return the value taken. This
 -- function is atomic only if there are no other producers fro this
 -- @MVar@.
+--
+-- @since 1.0.0.0
 swapMVar :: MonadConc m => MVar m a -> a -> m a
 swapMVar cvar a = mask_ $ do
   old <- takeMVar cvar
@@ -61,6 +63,8 @@
   return old
 
 -- | Check if a @MVar@ is empty.
+--
+-- @since 1.0.0.0
 isEmptyMVar :: MonadConc m => MVar m a -> m Bool
 isEmptyMVar cvar = do
   val <- tryTakeMVar cvar
@@ -72,6 +76,8 @@
 -- finishing. This operation is exception-safe: it will replace the
 -- original contents of the @MVar@ if an exception is raised. However,
 -- it is only atomic if there are no other producers for this @MVar@.
+--
+-- @since 1.0.0.0
 {-# INLINE withMVar #-}
 withMVar :: MonadConc m => MVar m a -> (a -> m b) -> m b
 withMVar cvar f = mask $ \restore -> do
@@ -83,6 +89,8 @@
 
 -- | Like 'withMVar', but the @IO@ action in the second argument is
 -- executed with asynchronous exceptions masked.
+--
+-- @since 1.0.0.0
 {-# INLINE withMVarMasked #-}
 withMVarMasked :: MonadConc m => MVar m a -> (a -> m b) -> m b
 withMVarMasked cvar f = mask_ $ do
@@ -97,12 +105,16 @@
 -- the @MVar@ if an exception is raised during the operation. This
 -- function is only atomic if there are no other producers for this
 -- @MVar@.
+--
+-- @since 1.0.0.0
 {-# INLINE modifyMVar_ #-}
 modifyMVar_ :: MonadConc m => MVar m a -> (a -> m a) -> m ()
 modifyMVar_ cvar f = modifyMVar cvar $ fmap (\a -> (a,())) . f
 
 -- | A slight variation on 'modifyMVar_' that allows a value to be
 -- returned (@b@) in addition to the modified value of the @MVar@.
+--
+-- @since 1.0.0.0
 {-# INLINE modifyMVar #-}
 modifyMVar :: MonadConc m => MVar m a -> (a -> m (a, b)) -> m b
 modifyMVar cvar f = mask $ \restore -> do
@@ -113,12 +125,16 @@
 
 -- | Like 'modifyMVar_', but the @IO@ action in the second argument is
 -- executed with asynchronous exceptions masked.
+--
+-- @since 1.0.0.0
 {-# INLINE modifyMVarMasked_ #-}
 modifyMVarMasked_ :: MonadConc m => MVar m a -> (a -> m a) -> m ()
 modifyMVarMasked_ cvar f = modifyMVarMasked cvar $ fmap (\a -> (a,())) . f
 
 -- | Like 'modifyMVar', but the @IO@ action in the second argument is
 -- executed with asynchronous exceptions masked.
+--
+-- @since 1.0.0.0
 {-# INLINE modifyMVarMasked #-}
 modifyMVarMasked :: MonadConc m => MVar m a -> (a -> m (a, b)) -> m b
 modifyMVarMasked cvar f = mask_ $ do
diff --git a/Control/Concurrent/Classy/QSem.hs b/Control/Concurrent/Classy/QSem.hs
--- a/Control/Concurrent/Classy/QSem.hs
+++ b/Control/Concurrent/Classy/QSem.hs
@@ -27,19 +27,27 @@
 -- > bracket_ qaitQSem signalSSem (...)
 --
 -- is safe; it never loses a unit of the resource.
+--
+-- @since 1.0.0.0
 newtype QSem m = QSem (QSemN m)
 
 -- | Build a new 'QSem' with a supplied initial quantity. The initial
 -- quantity must be at least 0.
+--
+-- @since 1.0.0.0
 newQSem :: MonadConc m => Int -> m (QSem m)
 newQSem initial
   | initial < 0 = fail "newQSem: Initial quantity mus tbe non-negative."
   | otherwise   = QSem <$> newQSemN initial
 
 -- | Wait for a unit to become available.
+--
+-- @since 1.0.0.0
 waitQSem :: MonadConc m => QSem m -> m ()
 waitQSem (QSem qSemN) = waitQSemN qSemN 1
 
 -- | Signal that a unit of the 'QSem' is available.
+--
+-- @since 1.0.0.0
 signalQSem :: MonadConc m => QSem m -> m ()
 signalQSem (QSem qSemN) = signalQSemN qSemN 1
diff --git a/Control/Concurrent/Classy/QSemN.hs b/Control/Concurrent/Classy/QSemN.hs
--- a/Control/Concurrent/Classy/QSemN.hs
+++ b/Control/Concurrent/Classy/QSemN.hs
@@ -30,16 +30,22 @@
 -- > bracket_ (waitQSemN n) (signalQSemN n) (...)
 --
 -- is safe; it never loses any of the resource.
+--
+-- @since 1.0.0.0
 newtype QSemN m = QSemN (MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())]))
 
 -- | Build a new 'QSemN' with a supplied initial quantity.
 --  The initial quantity must be at least 0.
+--
+-- @since 1.0.0.0
 newQSemN :: MonadConc m => Int -> m (QSemN m)
 newQSemN initial
   | initial < 0 = fail "newQSemN: Initial quantity must be non-negative"
   | otherwise   = QSemN <$> newMVar (initial, [], [])
 
 -- | Wait for the specified quantity to become available
+--
+-- @since 1.0.0.0
 waitQSemN :: MonadConc m => QSemN m -> Int -> m ()
 waitQSemN (QSemN m) sz = mask_ $ do
   (quantity, b1, b2) <- takeMVar m
@@ -64,6 +70,8 @@
       putMVar m r')
 
 -- | Signal that a given quantity is now available from the 'QSemN'.
+--
+-- @since 1.0.0.0
 signalQSemN :: MonadConc m => QSemN m -> Int -> m ()
 signalQSemN (QSemN m) sz = uninterruptibleMask_ $ do
   r  <- takeMVar m
diff --git a/Control/Concurrent/Classy/STM/TArray.hs b/Control/Concurrent/Classy/STM/TArray.hs
--- a/Control/Concurrent/Classy/STM/TArray.hs
+++ b/Control/Concurrent/Classy/STM/TArray.hs
@@ -28,8 +28,11 @@
 -- It is currently implemented as @Array ix (TVar stm e)@, but it may
 -- be replaced by a more efficient implementation in the future (the
 -- interface will remain the same, however).
+--
+-- @since 1.0.0.0
 newtype TArray stm i e = TArray (Array i (TVar stm e))
 
+-- | @since 1.0.0.0
 instance MonadSTM stm => MArray (TArray stm) e stm where
   getBounds (TArray a) = pure (bounds a)
 
diff --git a/Control/Concurrent/Classy/STM/TBQueue.hs b/Control/Concurrent/Classy/STM/TBQueue.hs
--- a/Control/Concurrent/Classy/STM/TBQueue.hs
+++ b/Control/Concurrent/Classy/STM/TBQueue.hs
@@ -37,6 +37,8 @@
 
 -- | 'TBQueue' is an abstract type representing a bounded FIFO
 -- channel.
+--
+-- @since 1.0.0.0
 data TBQueue stm a
    = TBQueue (TVar stm Int)
              (TVar stm [a])
@@ -44,6 +46,8 @@
              (TVar stm [a])
 
 -- | Build and returns a new instance of 'TBQueue'
+--
+-- @since 1.0.0.0
 newTBQueue :: MonadSTM stm
   => Int   -- ^ maximum number of elements the queue can hold
   -> stm (TBQueue stm a)
@@ -55,6 +59,8 @@
   pure (TBQueue rsize readT wsize writeT)
 
 -- | Write a value to a 'TBQueue'; retries if the queue is full.
+--
+-- @since 1.0.0.0
 writeTBQueue :: MonadSTM stm => TBQueue stm a -> a -> stm ()
 writeTBQueue (TBQueue rsize _ wsize writeT) a = do
   w <- readTVar wsize
@@ -71,6 +77,8 @@
   writeTVar writeT (a:listend)
 
 -- | Read the next value from the 'TBQueue'.
+--
+-- @since 1.0.0.0
 readTBQueue :: MonadSTM stm => TBQueue stm a -> stm a
 readTBQueue (TBQueue rsize readT _ writeT) = do
   xs <- readTVar readT
@@ -92,11 +100,15 @@
 
 -- | A version of 'readTBQueue' which does not retry. Instead it
 -- returns @Nothing@ if no value is available.
+--
+-- @since 1.0.0.0
 tryReadTBQueue :: MonadSTM stm => TBQueue stm a -> stm (Maybe a)
 tryReadTBQueue c = (Just <$> readTBQueue c) `orElse` pure Nothing
 
 -- | Get the next value from the @TBQueue@ without removing it,
 -- retrying if the channel is empty.
+--
+-- @since 1.0.0.0
 peekTBQueue :: MonadSTM stm => TBQueue stm a -> stm a
 peekTBQueue c = do
   x <- readTBQueue c
@@ -105,6 +117,8 @@
 
 -- | A version of 'peekTBQueue' which does not retry. Instead it
 -- returns @Nothing@ if no value is available.
+--
+-- @since 1.0.0.0
 tryPeekTBQueue :: MonadSTM stm => TBQueue stm a -> stm (Maybe a)
 tryPeekTBQueue c = do
   m <- tryReadTBQueue c
@@ -116,6 +130,8 @@
 
 -- | Put a data item back onto a channel, where it will be the next item read.
 -- Retries if the queue is full.
+--
+-- @since 1.0.0.0
 unGetTBQueue :: MonadSTM stm => TBQueue stm a -> a -> stm ()
 unGetTBQueue (TBQueue rsize readT wsize _) a = do
   r <- readTVar rsize
@@ -130,6 +146,8 @@
   writeTVar readT (a:xs)
 
 -- | Returns 'True' if the supplied 'TBQueue' is empty.
+--
+-- @since 1.0.0.0
 isEmptyTBQueue :: MonadSTM stm => TBQueue stm a -> stm Bool
 isEmptyTBQueue (TBQueue _ readT _ writeT) = do
   xs <- readTVar readT
@@ -138,6 +156,8 @@
     [] -> null <$> readTVar writeT
 
 -- | Returns 'True' if the supplied 'TBQueue' is full.
+--
+-- @since 1.0.0.0
 isFullTBQueue :: MonadSTM stm => TBQueue stm a -> stm Bool
 isFullTBQueue (TBQueue rsize _ wsize _) = do
   w <- readTVar wsize
diff --git a/Control/Concurrent/Classy/STM/TChan.hs b/Control/Concurrent/Classy/STM/TChan.hs
--- a/Control/Concurrent/Classy/STM/TChan.hs
+++ b/Control/Concurrent/Classy/STM/TChan.hs
@@ -36,6 +36,8 @@
 
 -- | 'TChan' is an abstract type representing an unbounded FIFO
 -- channel.
+--
+-- @since 1.0.0.0
 data TChan stm a = TChan (TVar stm (TVarList stm a))
                          (TVar stm (TVarList stm a))
 
@@ -43,6 +45,8 @@
 data TList stm a = TNil | TCons a (TVarList stm a)
 
 -- |Build and return a new instance of 'TChan'
+--
+-- @since 1.0.0.0
 newTChan :: MonadSTM stm => stm (TChan stm a)
 newTChan = do
   hole   <- newTVar TNil
@@ -53,6 +57,8 @@
 -- | Create a write-only 'TChan'.  More precisely, 'readTChan' will 'retry'
 -- even after items have been written to the channel.  The only way to
 -- read a broadcast channel is to duplicate it with 'dupTChan'.
+--
+-- @since 1.0.0.0
 newBroadcastTChan :: MonadSTM stm => stm (TChan stm a)
 newBroadcastTChan = do
     hole   <- newTVar TNil
@@ -61,6 +67,8 @@
     pure (TChan readT writeT)
 
 -- | Write a value to a 'TChan'.
+--
+-- @since 1.0.0.0
 writeTChan :: MonadSTM stm => TChan stm a -> a -> stm ()
 writeTChan (TChan _ writeT) a = do
   listend  <- readTVar writeT
@@ -69,11 +77,15 @@
   writeTVar writeT listend'
 
 -- | Read the next value from the 'TChan'.
+--
+-- @since 1.0.0.0
 readTChan :: MonadSTM stm => TChan stm a -> stm a
 readTChan tchan = tryReadTChan tchan >>= maybe retry pure
 
 -- | A version of 'readTChan' which does not retry. Instead it
 -- returns @Nothing@ if no value is available.
+--
+-- @since 1.0.0.0
 tryReadTChan :: MonadSTM stm => TChan stm a -> stm (Maybe a)
 tryReadTChan (TChan readT _) = do
   listhead <- readTVar readT
@@ -86,11 +98,15 @@
 
 -- | Get the next value from the 'TChan' without removing it,
 -- retrying if the channel is empty.
+--
+-- @since 1.0.0.0
 peekTChan :: MonadSTM stm => TChan stm a -> stm a
 peekTChan tchan = tryPeekTChan tchan >>= maybe retry pure
 
 -- | A version of 'peekTChan' which does not retry. Instead it
 -- returns @Nothing@ if no value is available.
+--
+-- @since 1.0.0.0
 tryPeekTChan :: MonadSTM stm => TChan stm a -> stm (Maybe a)
 tryPeekTChan (TChan readT _) = do
   listhead <- readTVar readT
@@ -103,6 +119,8 @@
 -- either channel from then on will be available from both.  Hence
 -- this creates a kind of broadcast channel, where data written by
 -- anyone is seen by everyone else.
+--
+-- @since 1.0.0.0
 dupTChan :: MonadSTM stm => TChan stm a -> stm (TChan stm a)
 dupTChan (TChan _ writeT) = do
   hole   <- readTVar writeT
@@ -111,6 +129,8 @@
 
 -- | Put a data item back onto a channel, where it will be the next
 -- item read.
+--
+-- @since 1.0.0.0
 unGetTChan :: MonadSTM stm => TChan stm a -> a -> stm ()
 unGetTChan (TChan readT _) a = do
    listhead <- readTVar readT
@@ -118,6 +138,8 @@
    writeTVar readT head'
 
 -- | Returns 'True' if the supplied 'TChan' is empty.
+--
+-- @since 1.0.0.0
 isEmptyTChan :: MonadSTM stm => TChan stm a -> stm Bool
 isEmptyTChan (TChan readT _) = do
   listhead <- readTVar readT
@@ -128,6 +150,8 @@
 
 -- | Clone a 'TChan': similar to 'dupTChan', but the cloned channel starts with the
 -- same content available as the original channel.
+--
+-- @since 1.0.0.0
 cloneTChan :: MonadSTM stm => TChan stm a -> stm (TChan stm a)
 cloneTChan (TChan readT writeT) = do
   readpos <- readTVar readT
diff --git a/Control/Concurrent/Classy/STM/TMVar.hs b/Control/Concurrent/Classy/STM/TMVar.hs
--- a/Control/Concurrent/Classy/STM/TMVar.hs
+++ b/Control/Concurrent/Classy/STM/TMVar.hs
@@ -36,9 +36,13 @@
 -- | A @TMVar@ is like an @MVar@ or a @mVar@, but using transactional
 -- memory. As transactions are atomic, this makes dealing with
 -- multiple @TMVar@s easier than wrangling multiple @mVar@s.
+--
+-- @since 1.0.0.0
 newtype TMVar stm a = TMVar (TVar stm (Maybe a))
 
 -- | Create a 'TMVar' containing the given value.
+--
+-- @since 1.0.0.0
 newTMVar :: MonadSTM stm => a -> stm (TMVar stm a)
 newTMVar = newTMVarN ""
 
@@ -47,6 +51,8 @@
 --
 -- Name conflicts are handled as usual for 'TVar's. The name is
 -- prefixed with \"ctmvar-\".
+--
+-- @since 1.0.0.0
 newTMVarN :: MonadSTM stm => String -> a -> stm (TMVar stm a)
 newTMVarN n a = do
   let n' = if null n then "ctmvar" else "ctmvar-" ++ n
@@ -54,6 +60,8 @@
   return $ TMVar ctvar
 
 -- | Create a new empty 'TMVar'.
+--
+-- @since 1.0.0.0
 newEmptyTMVar :: MonadSTM stm => stm (TMVar stm a)
 newEmptyTMVar = newEmptyTMVarN ""
 
@@ -61,6 +69,8 @@
 --
 -- Name conflicts are handled as usual for 'TVar's. The name is
 -- prefixed with \"ctmvar-\".
+--
+-- @since 1.0.0.0
 newEmptyTMVarN :: MonadSTM stm => String -> stm (TMVar stm a)
 newEmptyTMVarN n = do
   let n' = if null n then "ctmvar" else "ctmvar-" ++ n
@@ -68,18 +78,24 @@
   return $ TMVar ctvar
 
 -- | Take the contents of a 'TMVar', or 'retry' if it is empty.
+--
+-- @since 1.0.0.0
 takeTMVar :: MonadSTM stm => TMVar stm a -> stm a
 takeTMVar ctmvar = do
   taken <- tryTakeTMVar ctmvar
   maybe retry return taken
 
 -- | Write to a 'TMVar', or 'retry' if it is full.
+--
+-- @since 1.0.0.0
 putTMVar :: MonadSTM stm => TMVar stm a -> a -> stm ()
 putTMVar ctmvar a = do
   putted <- tryPutTMVar ctmvar a
   unless putted retry
 
 -- | Read from a 'TMVar' without emptying, or 'retry' if it is empty.
+--
+-- @since 1.0.0.0
 readTMVar :: MonadSTM stm => TMVar stm a -> stm a
 readTMVar ctmvar = do
   readed <- tryReadTMVar ctmvar
@@ -87,6 +103,8 @@
 
 -- | Try to take the contents of a 'TMVar', returning 'Nothing' if it
 -- is empty.
+--
+-- @since 1.0.0.0
 tryTakeTMVar :: MonadSTM stm => TMVar stm a -> stm (Maybe a)
 tryTakeTMVar (TMVar ctvar) = do
   val <- readTVar ctvar
@@ -94,6 +112,8 @@
   return val
 
 -- | Try to write to a 'TMVar', returning 'False' if it is full.
+--
+-- @since 1.0.0.0
 tryPutTMVar :: MonadSTM stm => TMVar stm a -> a -> stm Bool
 tryPutTMVar (TMVar ctvar) a = do
   val <- readTVar ctvar
@@ -102,15 +122,21 @@
 
 -- | Try to read from a 'TMVar' without emptying, returning 'Nothing'
 -- if it is empty.
+--
+-- @since 1.0.0.0
 tryReadTMVar :: MonadSTM stm => TMVar stm a -> stm (Maybe a)
 tryReadTMVar (TMVar ctvar) = readTVar ctvar
 
 -- | Check if a 'TMVar' is empty or not.
+--
+-- @since 1.0.0.0
 isEmptyTMVar :: MonadSTM stm => TMVar stm a -> stm Bool
 isEmptyTMVar ctmvar = isNothing `liftM` tryReadTMVar ctmvar
 
 -- | Swap the contents of a 'TMVar' returning the old contents, or
 -- 'retry' if it is empty.
+--
+-- @since 1.0.0.0
 swapTMVar :: MonadSTM stm => TMVar stm a -> a -> stm a
 swapTMVar ctmvar a = do
   val <- takeTMVar ctmvar
diff --git a/Control/Concurrent/Classy/STM/TQueue.hs b/Control/Concurrent/Classy/STM/TQueue.hs
--- a/Control/Concurrent/Classy/STM/TQueue.hs
+++ b/Control/Concurrent/Classy/STM/TQueue.hs
@@ -39,10 +39,14 @@
 import Control.Monad.STM.Class
 
 -- | 'TQueue' is an abstract type representing an unbounded FIFO channel.
+--
+-- @since 1.0.0.0
 data TQueue stm a = TQueue (TVar stm [a])
                            (TVar stm [a])
 
 -- | Build and returns a new instance of 'TQueue'
+--
+-- @since 1.0.0.0
 newTQueue :: MonadSTM stm => stm (TQueue stm a)
 newTQueue = do
   readT  <- newTVar []
@@ -50,12 +54,16 @@
   pure (TQueue readT writeT)
 
 -- | Write a value to a 'TQueue'.
+--
+-- @since 1.0.0.0
 writeTQueue :: MonadSTM stm => TQueue stm a -> a -> stm ()
 writeTQueue (TQueue _ writeT) a = do
   listend <- readTVar writeT
   writeTVar writeT (a:listend)
 
 -- | Read the next value from the 'TQueue'.
+--
+-- @since 1.0.0.0
 readTQueue :: MonadSTM stm => TQueue stm a -> stm a
 readTQueue (TQueue readT writeT) = do
   xs <- readTVar readT
@@ -76,11 +84,15 @@
 
 -- | A version of 'readTQueue' which does not retry. Instead it
 -- returns @Nothing@ if no value is available.
+--
+-- @since 1.0.0.0
 tryReadTQueue :: MonadSTM stm => TQueue stm a -> stm (Maybe a)
 tryReadTQueue c = (Just <$> readTQueue c) `orElse` pure Nothing
 
 -- | Get the next value from the @TQueue@ without removing it,
 -- retrying if the channel is empty.
+--
+-- @since 1.0.0.0
 peekTQueue :: MonadSTM stm => TQueue stm a -> stm a
 peekTQueue c = do
   x <- readTQueue c
@@ -89,6 +101,8 @@
 
 -- | A version of 'peekTQueue' which does not retry. Instead it
 -- returns @Nothing@ if no value is available.
+--
+-- @since 1.0.0.0
 tryPeekTQueue :: MonadSTM stm => TQueue stm a -> stm (Maybe a)
 tryPeekTQueue c = do
   m <- tryReadTQueue c
@@ -99,12 +113,16 @@
       pure m
 
 -- |Put a data item back onto a channel, where it will be the next item read.
+--
+-- @since 1.0.0.0
 unGetTQueue :: MonadSTM stm => TQueue stm a -> a -> stm ()
 unGetTQueue (TQueue readT _) a = do
   xs <- readTVar readT
   writeTVar readT (a:xs)
 
 -- |Returns 'True' if the supplied 'TQueue' is empty.
+--
+-- @since 1.0.0.0
 isEmptyTQueue :: MonadSTM stm => TQueue stm a -> stm Bool
 isEmptyTQueue (TQueue readT writeT) = do
   xs <- readTVar readT
diff --git a/Control/Concurrent/Classy/STM/TVar.hs b/Control/Concurrent/Classy/STM/TVar.hs
--- a/Control/Concurrent/Classy/STM/TVar.hs
+++ b/Control/Concurrent/Classy/STM/TVar.hs
@@ -32,18 +32,24 @@
 -- * @TVar@s
 
 -- | Mutate the contents of a 'TVar'. This is non-strict.
+--
+-- @since 1.0.0.0
 modifyTVar :: MonadSTM stm => TVar stm a -> (a -> a) -> stm ()
 modifyTVar ctvar f = do
   a <- readTVar ctvar
   writeTVar ctvar $ f a
 
 -- | Mutate the contents of a 'TVar' strictly.
+--
+-- @since 1.0.0.0
 modifyTVar' :: MonadSTM stm => TVar stm a -> (a -> a) -> stm ()
 modifyTVar' ctvar f = do
   a <- readTVar ctvar
   writeTVar ctvar $! f a
 
 -- | Swap the contents of a 'TVar', returning the old value.
+--
+-- @since 1.0.0.0
 swapTVar :: MonadSTM stm => TVar stm a -> a -> stm a
 swapTVar ctvar a = do
   old <- readTVar ctvar
@@ -53,6 +59,8 @@
 -- | Set the value of returned 'TVar' to @True@ after a given number
 -- of microseconds. The caveats associated with 'threadDelay' also
 -- apply.
+--
+-- @since 1.0.0.0
 registerDelay :: MonadConc m => Int -> m (TVar (STM m) Bool)
 registerDelay delay = do
   var <- atomically (newTVar False)
diff --git a/Control/Monad/Conc/Class.hs b/Control/Monad/Conc/Class.hs
--- a/Control/Monad/Conc/Class.hs
+++ b/Control/Monad/Conc/Class.hs
@@ -50,7 +50,9 @@
   , throw
   , catch
   , mask
+  , Ca.mask_
   , uninterruptibleMask
+  , Ca.uninterruptibleMask_
 
   -- * Mutable State
   , newMVar
@@ -98,6 +100,8 @@
 --
 -- Every @MonadConc@ has an associated 'MonadSTM', transactions of
 -- which can be run atomically.
+--
+-- @since 1.0.0.0
 class ( Applicative m, Monad m
       , MonadCatch m, MonadThrow m, MonadMask m
       , MonadSTM (STM m)
@@ -129,31 +133,43 @@
     #-}
 
   -- | The associated 'MonadSTM' for this class.
+  --
+  -- @since 1.0.0.0
   type STM m :: * -> *
 
   -- | The mutable reference type, like 'MVar's. This may contain one
   -- value at a time, attempting to read or take from an \"empty\"
   -- @MVar@ will block until it is full, and attempting to put to a
   -- \"full\" @MVar@ will block until it is empty.
+  --
+  -- @since 1.0.0.0
   type MVar m :: * -> *
 
   -- | The mutable non-blocking reference type. These may suffer from
   -- relaxed memory effects if functions outside the set @newCRef@,
   -- @readCRef@, @atomicModifyCRef@, and @atomicWriteCRef@ are used.
+  --
+  -- @since 1.0.0.0
   type CRef m :: * -> *
 
   -- | When performing compare-and-swap operations on @CRef@s, a
   -- @Ticket@ is a proof that a thread observed a specific previous
   -- value.
+  --
+  -- @since 1.0.0.0
   type Ticket m :: * -> *
 
   -- | An abstract handle to a thread.
+  --
+  -- @since 1.0.0.0
   type ThreadId m :: *
 
   -- | Fork a computation to happen concurrently. Communication may
   -- happen over @MVar@s.
   --
   -- > fork ma = forkWithUnmask (\_ -> ma)
+  --
+  -- @since 1.0.0.0
   fork :: m () -> m (ThreadId m)
   fork ma = forkWithUnmask (\_ -> ma)
 
@@ -162,6 +178,8 @@
   -- not be used within a 'mask' or 'uninterruptibleMask'.
   --
   -- > forkWithUnmask = forkWithUnmaskN ""
+  --
+  -- @since 1.0.0.0
   forkWithUnmask :: ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)
   forkWithUnmask = forkWithUnmaskN ""
 
@@ -173,6 +191,8 @@
   -- numeric suffix, counting up from 1.
   --
   -- > forkWithUnmaskN _ = forkWithUnmask
+  --
+  -- @since 1.0.0.0
   forkWithUnmaskN :: String -> ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)
   forkWithUnmaskN _ = forkWithUnmask
 
@@ -183,6 +203,8 @@
   -- total number of capabilities as returned by 'getNumCapabilities'.
   --
   -- > forkOn c ma = forkOnWithUnmask c (\_ -> ma)
+  --
+  -- @since 1.0.0.0
   forkOn :: Int -> m () -> m (ThreadId m)
   forkOn c ma = forkOnWithUnmask c (\_ -> ma)
 
@@ -190,6 +212,8 @@
   -- given CPU, as with 'forkOn'.
   --
   -- > forkOnWithUnmask = forkOnWithUnmaskN ""
+  --
+  -- @since 1.0.0.0
   forkOnWithUnmask :: Int -> ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)
   forkOnWithUnmask = forkOnWithUnmaskN ""
 
@@ -197,20 +221,30 @@
   -- given CPU, as with 'forkOn'.
   --
   -- > forkOnWithUnmaskN _ = forkOnWithUnmask
+  --
+  -- @since 1.0.0.0
   forkOnWithUnmaskN :: String -> Int -> ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)
   forkOnWithUnmaskN _ = forkOnWithUnmask
 
   -- | Get the number of Haskell threads that can run simultaneously.
+  --
+  -- @since 1.0.0.0
   getNumCapabilities :: m Int
 
   -- | Set the number of Haskell threads that can run simultaneously.
+  --
+  -- @since 1.0.0.0
   setNumCapabilities :: Int -> m ()
 
   -- | Get the @ThreadId@ of the current thread.
+  --
+  -- @since 1.0.0.0
   myThreadId :: m (ThreadId m)
 
   -- | Allows a context-switch to any other currently runnable thread
   -- (if any).
+  --
+  -- @since 1.0.0.0
   yield :: m ()
 
   -- | Yields the current thread, and optionally suspends the current
@@ -221,12 +255,16 @@
   -- will never continue to run earlier than specified.
   --
   -- > threadDelay _ = yield
+  --
+  -- @since 1.0.0.0
   threadDelay :: Int -> m ()
   threadDelay _ = yield
 
   -- | Create a new empty @MVar@.
   --
   -- > newEmptyMVar = newEmptyMVarN ""
+  --
+  -- @since 1.0.0.0
   newEmptyMVar :: m (MVar m a)
   newEmptyMVar = newEmptyMVarN ""
 
@@ -238,43 +276,59 @@
   -- numeric suffix, counting up from 1.
   --
   -- > newEmptyMVarN _ = newEmptyMVar
+  --
+  -- @since 1.0.0.0
   newEmptyMVarN :: String -> m (MVar m a)
   newEmptyMVarN _ = newEmptyMVar
 
   -- | Put a value into a @MVar@. If there is already a value there,
   -- this will block until that value has been taken, at which point
   -- the value will be stored.
+  --
+  -- @since 1.0.0.0
   putMVar :: MVar m a -> a -> m ()
 
   -- | Attempt to put a value in a @MVar@ non-blockingly, returning
   -- 'True' (and filling the @MVar@) if there was nothing there,
   -- otherwise returning 'False'.
+  --
+  -- @since 1.0.0.0
   tryPutMVar :: MVar m a -> a -> m Bool
 
   -- | Block until a value is present in the @MVar@, and then return
   -- it. This does not \"remove\" the value, multiple reads are
   -- possible.
+  --
+  -- @since 1.0.0.0
   readMVar :: MVar m a -> m a
 
   -- | Attempt to read a value from a @MVar@ non-blockingly, returning
   -- a 'Just' (and emptying the @MVar@) if there is something there,
   -- otherwise returning 'Nothing'. As with 'readMVar', this does not
   -- \"remove\" the value.
+  --
+  -- @since 1.1.0.0
   tryReadMVar :: MVar m a -> m (Maybe a)
 
   -- | Take a value from a @MVar@. This \"empties\" the @MVar@,
   -- allowing a new value to be put in. This will block if there is no
   -- value in the @MVar@ already, until one has been put.
+  --
+  -- @since 1.0.0.0
   takeMVar :: MVar m a -> m a
 
   -- | Attempt to take a value from a @MVar@ non-blockingly, returning
   -- a 'Just' (and emptying the @MVar@) if there was something there,
   -- otherwise returning 'Nothing'.
+  --
+  -- @since 1.0.0.0
   tryTakeMVar :: MVar m a -> m (Maybe a)
 
   -- | Create a new reference.
   --
   -- > newCRef = newCRefN ""
+  --
+  -- @since 1.0.0.0
   newCRef :: a -> m (CRef m a)
   newCRef = newCRefN ""
 
@@ -286,37 +340,51 @@
   -- numeric suffix, counting up from 1.
   --
   -- > newCRefN _ = newCRef
+  --
+  -- @since 1.0.0.0
   newCRefN :: String -> a -> m (CRef m a)
   newCRefN _ = newCRef
 
   -- | Read the current value stored in a reference.
   --
   -- > readCRef cref = readForCAS cref >>= peekTicket
+  --
+  -- @since 1.0.0.0
   readCRef :: CRef m a -> m a
   readCRef cref = readForCAS cref >>= peekTicket
 
   -- | Atomically modify the value stored in a reference. This imposes
   -- a full memory barrier.
+  --
+  -- @since 1.0.0.0
   atomicModifyCRef :: CRef m a -> (a -> (a, b)) -> m b
 
   -- | Write a new value into an @CRef@, without imposing a memory
   -- barrier. This means that relaxed memory effects can be observed.
+  --
+  -- @since 1.0.0.0
   writeCRef :: CRef m a -> a -> m ()
 
   -- | Replace the value stored in a reference, with the
   -- barrier-to-reordering property that 'atomicModifyCRef' has.
   --
   -- > atomicWriteCRef r a = atomicModifyCRef r $ const (a, ())
+  --
+  -- @since 1.0.0.0
   atomicWriteCRef :: CRef m a -> a -> m ()
   atomicWriteCRef r a = atomicModifyCRef r $ const (a, ())
 
   -- | Read the current value stored in a reference, returning a
   -- @Ticket@, for use in future compare-and-swap operations.
+  --
+  -- @since 1.0.0.0
   readForCAS :: CRef m a -> m (Ticket m a)
 
   -- | Extract the actual Haskell value from a @Ticket@.
   --
   -- The @proxy m@ is to determine the @m@ in the @Ticket@ type.
+  --
+  -- @since 1.0.0.0
   peekTicket' :: proxy m -> Ticket m a -> a
 
   -- | Perform a machine-level compare-and-swap (CAS) operation on a
@@ -324,32 +392,44 @@
   -- most current value in the @CRef@.
   --
   -- This is strict in the \"new\" value argument.
+  --
+  -- @since 1.0.0.0
   casCRef :: CRef m a -> Ticket m a -> a -> m (Bool, Ticket m a)
 
   -- | A replacement for 'atomicModifyCRef' using a compare-and-swap.
   --
   -- This is strict in the \"new\" value argument.
+  --
+  -- @since 1.0.0.0
   modifyCRefCAS :: CRef m a -> (a -> (a, b)) -> m b
 
   -- | A variant of 'modifyCRefCAS' which doesn't return a result.
   --
   -- > modifyCRefCAS_ cref f = modifyCRefCAS cref (\a -> (f a, ()))
+  --
+  -- @since 1.0.0.0
   modifyCRefCAS_ :: CRef m a -> (a -> a) -> m ()
   modifyCRefCAS_ cref f = modifyCRefCAS cref (\a -> (f a, ()))
 
   -- | Perform an STM transaction atomically.
+  --
+  -- @since 1.0.0.0
   atomically :: STM m a -> m a
 
   -- | Read the current value stored in a @TVar@. This may be
   -- implemented differently for speed.
   --
   -- > readTVarConc = atomically . readTVar
+  --
+  -- @since 1.0.0.0
   readTVarConc :: TVar (STM m) a -> m a
   readTVarConc = atomically . readTVar
 
   -- | Throw an exception to the target thread. This blocks until the
   -- exception is delivered, and it is just as if the target thread
   -- had raised it with 'throw'. This can interrupt a blocked action.
+  --
+  -- @since 1.0.0.0
   throwTo :: Exception e => ThreadId m -> e -> m ()
 
 -------------------------------------------------------------------------------
@@ -359,6 +439,8 @@
 
 -- | Create a concurrent computation for the provided action, and
 -- return a @MVar@ which can be used to query the result.
+--
+-- @since 1.0.0.0
 spawn :: MonadConc m => m a -> m (MVar m a)
 spawn ma = do
   cvar <- newEmptyMVar
@@ -371,6 +453,8 @@
 --
 -- This function is useful for informing the parent when a child
 -- terminates, for example.
+--
+-- @since 1.0.0.0
 forkFinally :: MonadConc m => m a -> (Either SomeException a -> m ()) -> m (ThreadId m)
 forkFinally action and_then =
   mask $ \restore ->
@@ -379,6 +463,8 @@
 -- | Raise the 'ThreadKilled' exception in the target thread. Note
 -- that if the thread is prepared to catch this exception, it won't
 -- actually kill it.
+--
+-- @since 1.0.0.0
 killThread :: MonadConc m => ThreadId m -> m ()
 killThread tid = throwTo tid ThreadKilled
 
@@ -388,6 +474,8 @@
 -- If no name is given, the @ThreadId@ is used. If names conflict,
 -- successive threads with the same name are given a numeric suffix,
 -- counting up from 1.
+--
+-- @since 1.0.0.0
 forkN :: MonadConc m => String -> m () -> m (ThreadId m)
 forkN name ma = forkWithUnmaskN name (\_ -> ma)
 
@@ -397,16 +485,22 @@
 -- If no name is given, the @ThreadId@ is used. If names conflict,
 -- successive threads with the same name are given a numeric suffix,
 -- counting up from 1.
+--
+-- @since 1.0.0.0
 forkOnN :: MonadConc m => String -> Int -> m () -> m (ThreadId m)
 forkOnN name i ma = forkOnWithUnmaskN name i (\_ -> ma)
 
 -- Bound Threads
 
 -- | Provided for compatibility, always returns 'False'.
+--
+-- @since 1.0.0.0
 rtsSupportsBoundThreads :: Bool
 rtsSupportsBoundThreads = False
 
 -- | Provided for compatibility, always returns 'False'.
+--
+-- @since 1.0.0.0
 isCurrentThreadBound :: MonadConc m => m Bool
 isCurrentThreadBound = pure False
 
@@ -415,6 +509,8 @@
 -- | Throw an exception. This will \"bubble up\" looking for an
 -- exception handler capable of dealing with it and, if one is not
 -- found, the thread is killed.
+--
+-- @since 1.0.0.0
 throw :: (MonadConc m, Exception e) => e -> m a
 throw = Ca.throwM
 
@@ -422,6 +518,8 @@
 -- exceptions raised by 'throw', unlike the more general
 -- Control.Exception.catch function. If you need to be able to catch
 -- /all/ errors, you will have to use 'IO'.
+--
+-- @since 1.0.0.0
 catch :: (MonadConc m, Exception e) => m a -> (e -> m a) -> m a
 catch = Ca.catch
 
@@ -435,6 +533,8 @@
 -- prevailing masking state within the context of the masked
 -- computation. This function should not be used within an
 -- 'uninterruptibleMask'.
+--
+-- @since 1.0.0.0
 mask :: MonadConc m => ((forall a. m a -> m a) -> m b) -> m b
 mask = Ca.mask
 
@@ -448,12 +548,16 @@
 -- interruptible operation will only block for a short period of
 -- time. The supplied unmasking function should not be used within a
 -- 'mask'.
+--
+-- @since 1.0.0.0
 uninterruptibleMask :: MonadConc m => ((forall a. m a -> m a) -> m b) -> m b
 uninterruptibleMask = Ca.uninterruptibleMask
 
 -- Mutable Variables
 
 -- | Create a new @MVar@ containing a value.
+--
+-- @since 1.0.0.0
 newMVar :: MonadConc m => a -> m (MVar m a)
 newMVar a = do
   cvar <- newEmptyMVar
@@ -466,6 +570,8 @@
 -- If no name is given, a counter starting from 0 is used. If names
 -- conflict, successive @MVar@s with the same name are given a numeric
 -- suffix, counting up from 1.
+--
+-- @since 1.0.0.0
 newMVarN :: MonadConc m => String -> a -> m (MVar m a)
 newMVarN n a = do
   cvar <- newEmptyMVarN n
@@ -476,11 +582,15 @@
 --
 -- This doesn't do do any monadic computation, the @m@ appears in the
 -- result type to determine the @m@ in the @Ticket@ type.
+--
+-- @since 1.0.0.0
 peekTicket :: forall m a. MonadConc m => Ticket m a -> m a
 peekTicket t = pure $ peekTicket' (Proxy :: Proxy m) (t :: Ticket m a)
 
 -- | Compare-and-swap a value in a @CRef@, returning an indication of
 -- success and the new value.
+--
+-- @since 1.0.0.0
 cas :: MonadConc m => CRef m a -> a -> m (Bool, a)
 cas cref a = do
   tick         <- readForCAS cref
@@ -492,6 +602,7 @@
 -------------------------------------------------------------------------------
 -- Concrete instances
 
+-- | @since 1.0.0.0
 instance MonadConc IO where
   type STM      IO = IO.STM
   type MVar     IO = IO.MVar
@@ -578,29 +689,47 @@
 
 -- | New threads inherit the reader state of their parent, but do not
 -- communicate results back.
+--
+-- @since 1.0.0.0
 INSTANCE(ReaderT r, MonadConc m, id)
 
+-- | @since 1.0.0.0
 INSTANCE(IdentityT, MonadConc m, id)
 
 -- | New threads inherit the writer state of their parent, but do not
 -- communicate results back.
+--
+-- @since 1.0.0.0
 INSTANCE(WL.WriterT w, (MonadConc m, Monoid w), fst)
+
 -- | New threads inherit the writer state of their parent, but do not
 -- communicate results back.
+--
+-- @since 1.0.0.0
 INSTANCE(WS.WriterT w, (MonadConc m, Monoid w), fst)
 
 -- | New threads inherit the state of their parent, but do not
 -- communicate results back.
+--
+-- @since 1.0.0.0
 INSTANCE(SL.StateT s, MonadConc m, fst)
+
 -- | New threads inherit the state of their parent, but do not
 -- communicate results back.
+--
+-- @since 1.0.0.0
 INSTANCE(SS.StateT s, MonadConc m, fst)
 
 -- | New threads inherit the states of their parent, but do not
 -- communicate results back.
+--
+-- @since 1.0.0.0
 INSTANCE(RL.RWST r w s, (MonadConc m, Monoid w), (\(a,_,_) -> a))
+
 -- | New threads inherit the states of their parent, but do not
 -- communicate results back.
+--
+-- @since 1.0.0.0
 INSTANCE(RS.RWST r w s, (MonadConc m, Monoid w), (\(a,_,_) -> a))
 
 #undef INSTANCE
@@ -609,6 +738,8 @@
 
 -- | Given a function to remove the transformer-specific state, lift
 -- a function invocation.
+--
+-- @since 1.0.0.0
 liftedF :: (MonadTransControl t, MonadConc m)
   => (forall x. StT t x -> x)
   -> (m a -> m b)
@@ -618,6 +749,8 @@
 
 -- | Given a function to remove the transformer-specific state, lift
 -- a @fork(on)WithUnmask@ invocation.
+--
+-- @since 1.0.0.0
 liftedFork :: (MonadTransControl t, MonadConc m)
   => (forall x. StT t x -> x)
   -> (((forall x. m x -> m x) -> m a) -> m b)
diff --git a/Control/Monad/STM/Class.hs b/Control/Monad/STM/Class.hs
--- a/Control/Monad/STM/Class.hs
+++ b/Control/Monad/STM/Class.hs
@@ -52,6 +52,8 @@
 -- This class does not provide any way to run transactions, rather
 -- each 'MonadConc' has an associated @MonadSTM@ from which it can
 -- atomically run a transaction.
+--
+-- @since 1.0.0.0
 class Ca.MonadCatch stm => MonadSTM stm where
   {-# MINIMAL
         retry
@@ -64,23 +66,31 @@
   -- | The mutable reference type. These behave like 'TVar's, in that
   -- they always contain a value and updates are non-blocking and
   -- synchronised.
+  --
+  -- @since 1.0.0.0
   type TVar stm :: * -> *
 
   -- | Retry execution of this transaction because it has seen values
   -- in @TVar@s that it shouldn't have. This will result in the
   -- thread running the transaction being blocked until any @TVar@s
   -- referenced in it have been mutated.
+  --
+  -- @since 1.0.0.0
   retry :: stm a
 
   -- | Run the first transaction and, if it @retry@s, run the second
   -- instead. If the monad is an instance of
   -- 'Alternative'/'MonadPlus', 'orElse' should be the '(<|>)'/'mplus'
   -- function.
+  --
+  -- @since 1.0.0.0
   orElse :: stm a -> stm a -> stm a
 
   -- | Create a new @TVar@ containing the given value.
   --
   -- > newTVar = newTVarN ""
+  --
+  -- @since 1.0.0.0
   newTVar :: a -> stm (TVar stm a)
   newTVar = newTVarN ""
 
@@ -93,28 +103,41 @@
   -- a numeric suffix, counting up from 1.
   --
   -- > newTVarN _ = newTVar
+  --
+  -- @since 1.0.0.0
   newTVarN :: String -> a -> stm (TVar stm a)
   newTVarN _ = newTVar
 
   -- | Return the current value stored in a @TVar@.
+  --
+  -- @since 1.0.0.0
   readTVar :: TVar stm a -> stm a
 
   -- | Write the supplied value into the @TVar@.
+  --
+  -- @since 1.0.0.0
   writeTVar :: TVar stm a -> a -> stm ()
 
 -- | Check whether a condition is true and, if not, call @retry@.
+--
+-- @since 1.0.0.0
 check :: MonadSTM stm => Bool -> stm ()
 check b = unless b retry
 
 -- | Throw an exception. This aborts the transaction and propagates
 -- the exception.
+--
+-- @since 1.0.0.0
 throwSTM :: (MonadSTM stm, Exception e) => e -> stm a
 throwSTM = Ca.throwM
 
 -- | Handling exceptions from 'throwSTM'.
+--
+-- @since 1.0.0.0
 catchSTM :: (MonadSTM stm, Exception e) => stm a -> (e -> stm a) -> stm a
 catchSTM = Ca.catch
 
+-- | @since 1.0.0.0
 instance MonadSTM STM.STM where
   type TVar STM.STM = STM.TVar
 
@@ -138,17 +161,28 @@
   readTVar    = lift . readTVar     ; \
   writeTVar v = lift . writeTVar v  }
 
+-- | @since 1.0.0.0
 INSTANCE(ReaderT r, MonadSTM stm, id)
 
+-- | @since 1.0.0.0
 INSTANCE(IdentityT, MonadSTM stm, id)
 
+-- | @since 1.0.0.0
 INSTANCE(WL.WriterT w, (MonadSTM stm, Monoid w), fst)
+
+-- | @since 1.0.0.0
 INSTANCE(WS.WriterT w, (MonadSTM stm, Monoid w), fst)
 
+-- | @since 1.0.0.0
 INSTANCE(SL.StateT s, MonadSTM stm, fst)
+
+-- | @since 1.0.0.0
 INSTANCE(SS.StateT s, MonadSTM stm, fst)
 
+-- | @since 1.0.0.0
 INSTANCE(RL.RWST r w s, (MonadSTM stm, Monoid w), (\(a,_,_) -> a))
+
+-- | @since 1.0.0.0
 INSTANCE(RS.RWST r w s, (MonadSTM stm, Monoid w), (\(a,_,_) -> a))
 
 #undef INSTANCE
@@ -157,6 +191,8 @@
 
 -- | Given a function to remove the transformer-specific state, lift
 -- an @orElse@ invocation.
+--
+-- @since 1.0.0.0
 liftedOrElse :: (MonadTransControl t, MonadSTM stm)
   => (forall x. StT t x -> x)
   -> t stm a -> t stm a -> t stm a
diff --git a/concurrency.cabal b/concurrency.cabal
--- a/concurrency.cabal
+++ b/concurrency.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                concurrency
-version:             1.1.1.0
+version:             1.1.2.0
 synopsis:            Typeclasses, functions, and data types for concurrency and STM.
 
 description:
@@ -84,7 +84,7 @@
 source-repository this
   type:     git
   location: https://github.com/barrucadu/dejafu.git
-  tag:      concurrency-1.1.1.0
+  tag:      concurrency-1.1.2.0
 
 library
   exposed-modules:     Control.Monad.Conc.Class
