Clean up and add documentation
This commit is contained in:
parent
d03e2922e9
commit
9636e1eb4d
1 changed files with 68 additions and 10 deletions
|
|
@ -1,24 +1,39 @@
|
|||
{-# LANGUAGE RecordWildCards #-}
|
||||
|
||||
-- | Chans that can be closed and reopened.
|
||||
--
|
||||
-- While a 'CloseableChan' is closed (or locked), it can not be written to or read from.
|
||||
-- Calls to 'writeChan' and 'readChan' are non-blocking while a chan is closed.
|
||||
--
|
||||
-- If a thread is attempting to read from a chan using 'readChan' and that chan is closed,
|
||||
-- the call to 'readChan' resumes and @Nothing@ is returned.
|
||||
|
||||
module EuphApi.CloseableChan
|
||||
( CloseableChan
|
||||
-- * IO versions
|
||||
, newCloseableChan
|
||||
-- * IO function versions
|
||||
, newOpenChan
|
||||
, newClosedChan
|
||||
, writeChan
|
||||
, readChan
|
||||
, closeChan
|
||||
, openChan
|
||||
, emptyChan
|
||||
-- * STM versions
|
||||
, newCloseableChanSTM
|
||||
-- * STM function versions
|
||||
, newOpenChanSTM
|
||||
, newClosedChanSTM
|
||||
, writeChanSTM
|
||||
, readChanSTM
|
||||
, closeChanSTM
|
||||
, openChanSTM
|
||||
, emptyChanSTM
|
||||
) where
|
||||
|
||||
import Control.Concurrent.STM
|
||||
import Control.Monad
|
||||
|
||||
-- | A 'Chan' that can be closed and opened again.
|
||||
--
|
||||
-- Attempts to write to or read from a 'CloseableChan' while it is closed result
|
||||
-- in a @Nothing@.
|
||||
data CloseableChan a = CloseableChan
|
||||
{ cClosed :: TVar Bool
|
||||
, cChan :: TChan (Content a)
|
||||
|
|
@ -31,12 +46,21 @@ data Content a = Value a
|
|||
- Functions as STM actions
|
||||
-}
|
||||
|
||||
newCloseableChanSTM :: STM (CloseableChan a)
|
||||
newCloseableChanSTM = do
|
||||
-- | See 'newOpenChan'.
|
||||
newOpenChanSTM :: STM (CloseableChan a)
|
||||
newOpenChanSTM = do
|
||||
cClosed <- newTVar False
|
||||
cChan <- newTChan
|
||||
return $ CloseableChan{..}
|
||||
|
||||
-- | See 'newClosedChan'.
|
||||
newClosedChanSTM :: STM (CloseableChan a)
|
||||
newClosedChanSTM = do
|
||||
cClosed <- newTVar True
|
||||
cChan <- newTChan
|
||||
return $ CloseableChan{..}
|
||||
|
||||
-- | See 'writeChan'.
|
||||
writeChanSTM :: CloseableChan a -> a -> STM (Maybe ())
|
||||
writeChanSTM CloseableChan{..} a = do
|
||||
closed <- readTVar cClosed
|
||||
|
|
@ -44,6 +68,7 @@ writeChanSTM CloseableChan{..} a = do
|
|||
then return Nothing
|
||||
else Just <$> writeTChan cChan (Value a)
|
||||
|
||||
-- | See 'readChan'.
|
||||
readChanSTM :: CloseableChan a -> STM (Maybe a)
|
||||
readChanSTM CloseableChan{..} = do
|
||||
closed <- readTVar cClosed
|
||||
|
|
@ -57,11 +82,18 @@ readChanSTM CloseableChan{..} = do
|
|||
End -> readValue -- ignore End while reading normally
|
||||
Value v -> return v
|
||||
|
||||
-- | See 'closeChan'.
|
||||
closeChanSTM :: CloseableChan a -> STM ()
|
||||
closeChanSTM CloseableChan{..} = do
|
||||
writeTVar cClosed True
|
||||
--writeTChan cChan End
|
||||
|
||||
-- | See 'openChan'.
|
||||
openChanSTM :: CloseableChan a -> STM ()
|
||||
openChanSTM CloseableChan{..} = do
|
||||
writeTVar cClosed False
|
||||
|
||||
-- | See 'emptyChan'.
|
||||
emptyChanSTM :: CloseableChan a -> STM [a]
|
||||
emptyChanSTM CloseableChan{..} = do
|
||||
writeTChan cChan End
|
||||
|
|
@ -77,17 +109,43 @@ emptyChanSTM CloseableChan{..} = do
|
|||
- Functions as IO actions
|
||||
-}
|
||||
|
||||
newCloseableChan :: IO (CloseableChan a)
|
||||
newCloseableChan = atomically newCloseableChanSTM
|
||||
-- | Create a new open 'CloseableChan'.
|
||||
newOpenChan :: IO (CloseableChan a)
|
||||
newOpenChan = atomically newOpenChanSTM
|
||||
|
||||
-- | Create a new closed 'CloseableChan'.
|
||||
newClosedChan :: IO (CloseableChan a)
|
||||
newClosedChan = atomically newClosedChanSTM
|
||||
|
||||
-- | Attempt to write a value into the 'CloseableChan'.
|
||||
--
|
||||
-- If the chan is open, succeeds with a @Just ()@.
|
||||
-- If the chan is closed, fails with a @Nothing@.
|
||||
writeChan :: CloseableChan a -> a -> IO (Maybe ())
|
||||
writeChan chan = atomically . writeChanSTM chan
|
||||
writeChan chan a = atomically $ writeChanSTM chan a
|
||||
|
||||
-- | Attempt to read a value @v@ from the 'CloseableChan'.
|
||||
--
|
||||
-- If the chan is open, succeeds with a @Just v@.
|
||||
-- If the chan is closed, fails with a @Nothing@.
|
||||
readChan :: CloseableChan a -> IO (Maybe a)
|
||||
readChan = atomically . readChanSTM
|
||||
|
||||
-- | Close a 'CloseableChan'.
|
||||
-- Does nothing if chan is already closed.
|
||||
--
|
||||
-- Performing this action un-blocks all calls to 'readChan'.
|
||||
closeChan :: CloseableChan a -> IO ()
|
||||
closeChan = atomically . closeChanSTM
|
||||
|
||||
-- | Open a 'CloseableChan'.
|
||||
-- Does nothing if chan is already open.
|
||||
openChan :: CloseableChan a -> IO ()
|
||||
openChan = atomically . openChanSTM
|
||||
|
||||
-- | Remove all items currently in the 'CloseableChan' and returns them in a list.
|
||||
--
|
||||
-- This function also works while the chan is closed.
|
||||
-- It is meant as a way to clean up the remaining values in a chan after it was closed.
|
||||
emptyChan :: CloseableChan a -> IO [a]
|
||||
emptyChan = atomically . emptyChanSTM
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue