tryWriteTBMChan :: TBMChan a -> a -> STM (Maybe Bool)
tryWriteTBMChan self@(TBMChan closed limit chan) x = do
    b <- readTVar closed
    if b
        then return Nothing
        else do
            b' <- isFullTBMChan self
            if b'
                then return (Just False)
                else do
                    writeTChan chan x
                    modifyTVar' limit (subtract 1)
                    return (Just True)


-- | Put a data item back onto a channel, where it will be the next
-- item read. If the channel is closed then the value is silently
-- discarded; you can use 'peekTBMChan' to circumvent this in certain
-- circumstances. /N.B./, this could allow the channel to temporarily
-- become longer than the specified limit, which is necessary to
-- ensure that the item is indeed the next one read.
tryWriteTBMChan :: TBMChan a -> a -> STM (Maybe Bool)
tryWriteTBMChan self@(TBMChan closed limit chan) x = do
    b <- readTVar closed
    if b
        then return Nothing
        else do
            b' <- isFullTBMChan self
            if b'
                then return (Just False)
                else do
                    writeTChan chan x
                    modifyTVar' limit (subtract 1)
                    return (Just True)


-- | Put a data item back onto a channel, where it will be the next
-- item read. If the channel is closed then the value is silently
-- discarded; you can use 'peekTBMChan' to circumvent this in certain
-- circumstances. /N.B./, this could allow the channel to temporarily
-- become longer than the specified limit, which is necessary to
-- ensure that the item is indeed the next one read.
tryWriteTBMChan self@(TBMChan closed limit chan) x = do
    b <- readTVar closed
    if b
        then return Nothing
        else do
            b' <- isFullTBMChan self
            if b'
                then return (Just False)
                else do
                    writeTChan chan x
                    modifyTVar' limit (subtract 1)
                    return (Just True)


-- | Put a data item back onto a channel, where it will be the next
-- item read. If the channel is closed then the value is silently
-- discarded; you can use 'peekTBMChan' to circumvent this in certain
-- circumstances. /N.B./, this could allow the channel to temporarily
-- become longer than the specified limit, which is necessary to
-- ensure that the item is indeed the next one read.