diff --git a/Control/Concurrent/STM/TBQueue.hs b/Control/Concurrent/STM/TBQueue.hs
--- a/Control/Concurrent/STM/TBQueue.hs
+++ b/Control/Concurrent/STM/TBQueue.hs
@@ -45,6 +45,7 @@
         isFullTBQueue,
   ) where
 
+import           Control.Monad   (unless)
 import           Data.Typeable   (Typeable)
 import           GHC.Conc        (STM, TVar, newTVar, newTVarIO, orElse,
                                   readTVar, retry, writeTVar)
@@ -156,8 +157,8 @@
   if null xs && null ys
     then return []
     else do
-      writeTVar read []
-      writeTVar write []
+      unless (null xs) $ writeTVar read []
+      unless (null ys) $ writeTVar write []
       writeTVar rsize 0
       writeTVar wsize size
       return (xs ++ reverse ys)
diff --git a/Control/Concurrent/STM/TMVar.hs b/Control/Concurrent/STM/TMVar.hs
--- a/Control/Concurrent/STM/TMVar.hs
+++ b/Control/Concurrent/STM/TMVar.hs
@@ -30,6 +30,7 @@
         takeTMVar,
         putTMVar,
         readTMVar,
+        writeTMVar,
         tryReadTMVar,
         swapTMVar,
         tryTakeTMVar,
@@ -147,6 +148,11 @@
   case m of
     Nothing -> retry
     Just old -> do writeTVar t (Just new); return old
+
+-- | Non-blocking write of a new value to a 'TMVar'
+-- Puts if empty. Replaces if populated.
+writeTMVar :: TMVar a -> a -> STM ()
+writeTMVar t new = tryTakeTMVar t >> putTMVar t new
 
 -- |Check whether a given 'TMVar' is empty.
 isEmptyTMVar :: TMVar a -> STM Bool
diff --git a/Control/Monad/STM.hs b/Control/Monad/STM.hs
--- a/Control/Monad/STM.hs
+++ b/Control/Monad/STM.hs
@@ -68,7 +68,17 @@
 #endif
 #endif
 
+#if !MIN_VERSION_base(4,17,0)
+import Control.Monad (liftM2)
+#if !MIN_VERSION_base(4,11,0)
+import Data.Semigroup (Semigroup (..))
+#endif
+#if !MIN_VERSION_base(4,8,0)
+import Data.Monoid (Monoid (..))
+#endif
+#endif
 
+
 #ifdef __GLASGOW_HASKELL__
 #if ! (MIN_VERSION_base(4,3,0))
 instance MonadPlus STM where
@@ -137,3 +147,14 @@
     let ans        = liftSTM (k r) s
         STMret _ r = ans
     in case ans of STMret s' x -> (# s', x #)
+
+#if !MIN_VERSION_base(4,17,0)
+instance Semigroup a => Semigroup (STM a) where
+    (<>) = liftM2 (<>)
+
+instance Monoid a => Monoid (STM a) where
+    mempty = return mempty
+#if !MIN_VERSION_base(4,13,0)
+    mappend = liftM2 mappend
+#endif
+#endif
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,11 @@
 # Changelog for [`stm` package](http://hackage.haskell.org/package/stm)
 
+## 2.5.1.0 *Aug 2022*
+
+  * Teach `flushTBQueue` to only flush queue when necessary
+  * Introduce `Control.Concurrent.STM.TMVar.writeTMVar`
+  * Add `Semigroup` and `Monoid` instances for `STM`
+
 ## 2.5.0.2 *Dec 2021*
 
   * Fix non-exhaustive patterns warning (#49)
@@ -29,7 +35,7 @@
 
   * Fix incorrect bookkeeping of write capacity in `flushTBQueue` (gh-9)
 
-  * Avoid redundant `writeTVar`s in `flushTQueue` to avoid unncessarily
+  * Avoid redundant `writeTVar`s in `flushTQueue` to avoid unnecessarily
     invalidating other transactions (gh-6)
 
 ### 2.4.5.0 *Feb 2018*
diff --git a/stm.cabal b/stm.cabal
--- a/stm.cabal
+++ b/stm.cabal
@@ -1,6 +1,6 @@
 cabal-version:  >=1.10
 name:           stm
-version:        2.5.0.2
+version:        2.5.1.0
 -- don't forget to update changelog.md file!
 
 license:        BSD3
@@ -49,8 +49,11 @@
     if !impl(ghc >= 7.10)
         build-depends: nats (>= 0.1.3 && < 0.3) || (>= 1 && < 1.2)
 
+    if !impl(ghc >= 8.0)
+        build-depends: semigroups >=0.18.6 && <0.21
+
     build-depends:
-        base  >= 4.3 && < 4.17,
+        base  >= 4.4 && < 4.18,
         array >= 0.3 && < 0.6
 
     exposed-modules:
