Created
September 8, 2013 17:20
-
-
Save zearen/6486622 to your computer and use it in GitHub Desktop.
A sketch of a reverse semaphore for Haskell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Control.Concurrent.QSemR | |
( newQSemR | |
, bracketQSemR | |
, whenEmptyQSemR | |
) where | |
import Control.Exception (bracket) | |
import Control.Concurrent.MVar | |
type QSemR = (MVar (), MVar Int) | |
newQSemR :: IO QSemR | |
newQSemR = do | |
mvarStop <- newMVar () | |
mvarCount <- newMVar 0 | |
return $! (mvarStop, mvarCount) | |
enterQSemR :: QSemR -> IO () | |
enterQSemR (mvarStop, mvarCount) = do | |
tryTakeMVar mvarStop | |
modifyMVar_ mvarCount (return . (+1)) | |
leaveQSemR :: QSemR -> IO () | |
leaveQSemR (mvarStop, mvarCount) = | |
takeMVar mvarCount >>= actOn >>= putMVar mvarCount | |
where actOn count | |
-- One may wish to better define error state here | |
| count <= 0 = return 0 | |
| count == 1 = do | |
putMVar mvarStop () | |
return 0 | |
| otherwise = return $ count - 1 | |
bracketQSemR :: QSemR -> IO a -> IO a | |
bracketQSemR qSemR = bracket | |
(enterQSemR qSemR) | |
(const $ leaveQSemR qSemR) | |
. const | |
whenEmptyQSemR :: QSemR -> IO a -> IO a | |
whenEmptyQSemR (mvarStop, mvarCount) = bracket acquire release . const | |
where acquire = do | |
takeMVar mvarStop | |
takeMVar mvarCount | |
release _ = do | |
putMVar mvarStop () | |
putMVar mvarCount 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment