writeTBMChan :: TBMChan a -> a -> STM ()
writeTBMChan self@(TBMChan closed limit chan) x = do
    b <- readTVar closed
    if b
        then return () -- Discard silently
        else do
            b' <- isFullTBMChan self
            if b'
                then retry
                else do
                    writeTChan chan x
                    modifyTVar' limit (subtract 1)


-- | A version of 'writeTBMChan' which does not retry. Returns @Just
-- True@ if the value was successfully written, @Just False@ if it
-- could not be written (but the channel was open), and @Nothing@
-- if it was discarded (i.e., the channel was closed).
writeTBMChan :: TBMChan a -> a -> STM ()
writeTBMChan self@(TBMChan closed limit chan) x = do
    b <- readTVar closed
    if b
        then return () -- Discard silently
        else do
            b' <- isFullTBMChan self
            if b'
                then retry
                else do
                    writeTChan chan x
                    modifyTVar' limit (subtract 1)


-- | A version of 'writeTBMChan' which does not retry. Returns @Just
-- True@ if the value was successfully written, @Just False@ if it
-- could not be written (but the channel was open), and @Nothing@
-- if it was discarded (i.e., the channel was closed).
writeTBMChan self@(TBMChan closed limit chan) x = do
    b <- readTVar closed
    if b
        then return () -- Discard silently
        else do
            b' <- isFullTBMChan self
            if b'
                then retry
                else do
                    writeTChan chan x
                    modifyTVar' limit (subtract 1)


-- | A version of 'writeTBMChan' which does not retry. Returns @Just
-- True@ if the value was successfully written, @Just False@ if it
-- could not be written (but the channel was open), and @Nothing@
-- if it was discarded (i.e., the channel was closed).