From a630bae16eedfe32e508d9c925b692f1d1d32018 Mon Sep 17 00:00:00 2001
From: Nikita Volkov <nikita.y.volkov@mail.ru>
Date: Thu, 19 Oct 2023 18:45:24 +0300
Subject: [PATCH 1/3] Reproduce the bug in flushTBQueue

---
 testsuite/src/Issue76.hs  | 28 ++++++++++++++++++++++++++++
 testsuite/src/Main.hs     |  2 ++
 testsuite/testsuite.cabal |  1 +
 3 files changed, 31 insertions(+)
 create mode 100644 testsuite/src/Issue76.hs

diff --git a/testsuite/src/Issue76.hs b/testsuite/src/Issue76.hs
new file mode 100644
index 0000000..31b279d
--- /dev/null
+++ b/testsuite/src/Issue76.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE CPP #-}
+
+-- See https://github.com/haskell/stm/pull/76.
+--
+-- Test-case contributed by Nikita Volkov <nikita.y.volkov@mail.ru>.
+--
+-- This bug is observable in version `stm-2.5.2.1`.
+
+module Issue76 (main) where
+
+import Control.Concurrent.STM
+import Data.Foldable
+import Test.HUnit
+
+main :: IO ()
+#if MIN_VERSION_stm(2,4,5)
+main = do
+  queue <- newTBQueueIO 100 :: IO (TBQueue Int)
+  lengthAfterFlush <- atomically $ do
+    writeTBQueue queue 1
+    writeTBQueue queue 2
+    _ <- flushTBQueue queue
+    lengthTBQueue queue
+  assertEqual "" 0 lengthAfterFlush
+#else
+-- test-case not applicable; `flushTBQueue` was only added in 2.4.5.0
+main = return ()
+#endif
diff --git a/testsuite/src/Main.hs b/testsuite/src/Main.hs
index 8cbb8db..e7c8826 100644
--- a/testsuite/src/Main.hs
+++ b/testsuite/src/Main.hs
@@ -6,6 +6,7 @@ import           Test.Framework                 (defaultMain, testGroup)
 import           Test.Framework.Providers.HUnit
 
 import qualified Issue9
+import qualified Issue76
 import qualified Stm052
 import qualified Stm064
 import qualified Stm065
@@ -18,6 +19,7 @@ main = do
     tests = [
       testGroup "regression"
         [ testCase "issue #9" Issue9.main
+        , testCase "issue #76" Issue76.main
         , testCase "stm052" Stm052.main
         , testCase "stm064" Stm064.main
         , testCase "stm065" Stm065.main
diff --git a/testsuite/testsuite.cabal b/testsuite/testsuite.cabal
index 863057f..0652418 100644
--- a/testsuite/testsuite.cabal
+++ b/testsuite/testsuite.cabal
@@ -20,6 +20,7 @@ test-suite stm
   main-is: Main.hs
   other-modules:
     Issue9
+    Issue76
     Stm052
     Stm064
     Stm065

From dce77da76a467f4739b0d42cb9e17df1317dd37d Mon Sep 17 00:00:00 2001
From: Nikita Volkov <nikita.y.volkov@mail.ru>
Date: Thu, 19 Oct 2023 18:50:04 +0300
Subject: [PATCH 2/3] Provide a quick fix of flushTBQueue

---
 Control/Concurrent/STM/TBQueue.hs | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/Control/Concurrent/STM/TBQueue.hs b/Control/Concurrent/STM/TBQueue.hs
index d5ea578..58559f3 100644
--- a/Control/Concurrent/STM/TBQueue.hs
+++ b/Control/Concurrent/STM/TBQueue.hs
@@ -143,18 +143,15 @@ tryReadTBQueue q = fmap Just (readTBQueue q) `orElse` pure Nothing
 --
 -- @since 2.4.5
 flushTBQueue :: forall a. TBQueue a -> STM [a]
-flushTBQueue (TBQueue _rindex windex elements cap) = do
-  w <- readTVar windex
-  go (decMod w cap) []
- where
-  go :: Int -> [a] -> STM [a]
-  go i acc = do
-      ele <- unsafeRead elements i
-      case ele of
-        Nothing -> pure acc
-        Just a -> do
-          unsafeWrite elements i Nothing
-          go (decMod i cap) (a : acc)
+flushTBQueue queue =
+  -- TODO: Optimize.
+  go []
+  where
+    go acc = do
+      tryReadResult <- tryReadTBQueue queue
+      case tryReadResult of
+        Just element -> go $ element : acc
+        Nothing -> return $ reverse acc
 
 -- | Get the next value from the @TBQueue@ without removing it,
 -- retrying if the queue is empty.

From 4532c745bf4791585ee25930e91cf699f3a1db58 Mon Sep 17 00:00:00 2001
From: Nikita Volkov <nikita.y.volkov@mail.ru>
Date: Thu, 19 Oct 2023 19:17:10 +0300
Subject: [PATCH 3/3] Clean up

---
 testsuite/src/Issue76.hs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/testsuite/src/Issue76.hs b/testsuite/src/Issue76.hs
index 31b279d..21451d7 100644
--- a/testsuite/src/Issue76.hs
+++ b/testsuite/src/Issue76.hs
@@ -9,7 +9,6 @@
 module Issue76 (main) where
 
 import Control.Concurrent.STM
-import Data.Foldable
 import Test.HUnit
 
 main :: IO ()