Clean up and add documentation

This commit is contained in:
Joscha 2018-01-27 20:58:36 +00:00
parent d03e2922e9
commit 9636e1eb4d

View file

@ -1,24 +1,39 @@
{-# LANGUAGE RecordWildCards #-} {-# 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 module EuphApi.CloseableChan
( CloseableChan ( CloseableChan
-- * IO versions -- * IO function versions
, newCloseableChan , newOpenChan
, newClosedChan
, writeChan , writeChan
, readChan , readChan
, closeChan , closeChan
, openChan
, emptyChan , emptyChan
-- * STM versions -- * STM function versions
, newCloseableChanSTM , newOpenChanSTM
, newClosedChanSTM
, writeChanSTM , writeChanSTM
, readChanSTM , readChanSTM
, closeChanSTM , closeChanSTM
, openChanSTM
, emptyChanSTM , emptyChanSTM
) where ) where
import Control.Concurrent.STM 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 data CloseableChan a = CloseableChan
{ cClosed :: TVar Bool { cClosed :: TVar Bool
, cChan :: TChan (Content a) , cChan :: TChan (Content a)
@ -31,12 +46,21 @@ data Content a = Value a
- Functions as STM actions - Functions as STM actions
-} -}
newCloseableChanSTM :: STM (CloseableChan a) -- | See 'newOpenChan'.
newCloseableChanSTM = do newOpenChanSTM :: STM (CloseableChan a)
newOpenChanSTM = do
cClosed <- newTVar False cClosed <- newTVar False
cChan <- newTChan cChan <- newTChan
return $ CloseableChan{..} 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 -> a -> STM (Maybe ())
writeChanSTM CloseableChan{..} a = do writeChanSTM CloseableChan{..} a = do
closed <- readTVar cClosed closed <- readTVar cClosed
@ -44,6 +68,7 @@ writeChanSTM CloseableChan{..} a = do
then return Nothing then return Nothing
else Just <$> writeTChan cChan (Value a) else Just <$> writeTChan cChan (Value a)
-- | See 'readChan'.
readChanSTM :: CloseableChan a -> STM (Maybe a) readChanSTM :: CloseableChan a -> STM (Maybe a)
readChanSTM CloseableChan{..} = do readChanSTM CloseableChan{..} = do
closed <- readTVar cClosed closed <- readTVar cClosed
@ -57,11 +82,18 @@ readChanSTM CloseableChan{..} = do
End -> readValue -- ignore End while reading normally End -> readValue -- ignore End while reading normally
Value v -> return v Value v -> return v
-- | See 'closeChan'.
closeChanSTM :: CloseableChan a -> STM () closeChanSTM :: CloseableChan a -> STM ()
closeChanSTM CloseableChan{..} = do closeChanSTM CloseableChan{..} = do
writeTVar cClosed True writeTVar cClosed True
--writeTChan cChan End --writeTChan cChan End
-- | See 'openChan'.
openChanSTM :: CloseableChan a -> STM ()
openChanSTM CloseableChan{..} = do
writeTVar cClosed False
-- | See 'emptyChan'.
emptyChanSTM :: CloseableChan a -> STM [a] emptyChanSTM :: CloseableChan a -> STM [a]
emptyChanSTM CloseableChan{..} = do emptyChanSTM CloseableChan{..} = do
writeTChan cChan End writeTChan cChan End
@ -77,17 +109,43 @@ emptyChanSTM CloseableChan{..} = do
- Functions as IO actions - Functions as IO actions
-} -}
newCloseableChan :: IO (CloseableChan a) -- | Create a new open 'CloseableChan'.
newCloseableChan = atomically newCloseableChanSTM 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 :: 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 :: CloseableChan a -> IO (Maybe a)
readChan = atomically . readChanSTM 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 :: CloseableChan a -> IO ()
closeChan = atomically . closeChanSTM 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 :: CloseableChan a -> IO [a]
emptyChan = atomically . emptyChanSTM emptyChan = atomically . emptyChanSTM