Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,865
    • Issues 4,865
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 461
    • Merge requests 461
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #7104
Closed
Open
Created Jul 30, 2012 by joeyadams@trac-joeyadams

Add tryWriteTBQueue to Control.Concurrent.STM.TBQueue

I'd like a "try" variant of writeTBQueue, so part of my application can react to the queue overflowing by returning a "queue is full" status.

Attached is a series of patches, the last of which adds writeTBQueue. The other patches fix a couple minor issues:

  • Force capacity computations, so a long series of readTBQueue calls won't lead to a stack overflow.
  • Guard against negative queue size given to newTBQueue and newTBQueueIO.

While we're at it, I have a couple general questions about retry and orElse:

  • Is atomically (retry orElse return ()) guaranteed to not be interruptible by an asynchronous exception when exceptions are masked?
  • Is there a performance benefit to avoiding retry when possible? I'd imagine not, since this should only involve throwing away a few transaction log entries.

If atomically (retry orElse return ()) is guaranteed to not be interruptible, and if there is no performance benefit to avoiding retry, then it seems there's little point in having any of the try* functions.

In the documentation for Control.Exception, it lists operations that are guaranteed to not be interruptible. One of them is:

  • STM transactions that do not use retry

This is a useful property, and is expected of any "try" function. However, tryReadTBQueue "uses" retry.

I did a quick test, and it looks like atomically (retry orElse return ()) is not interruptible:

import Control.Concurrent
import Control.Concurrent.STM
import Control.Exception
import Control.Monad

repeatSTM :: STM () -> IO ()
repeatSTM = replicateM_ 50000000 . atomically

main :: IO ()
main = do
    finished <- newEmptyMVar

    tid <- mask_ $ forkOS $ do
        repeatSTM (retry `orElse` return ())
        putMVar finished ()

    threadDelay 100000
    killThread tid  -- should wait for the thread to run to completion

    putStrLn "Let's see if the thread finished..."
    takeMVar finished
    putStrLn "Yes, it did."

Is this guaranteed in general? That is, if the transaction does retry calls, but the transaction as a whole does not retry due to orElse, is the transaction guaranteed to not be interruptible?

Trac metadata
Trac field Value
Version 7.4.2
Type FeatureRequest
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component libraries (other)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking