Stability | experimental |
---|---|
Maintainer | Adam Langley <[email protected]> |
Network.Connection
Contents
Description
Helpful functions to deal with stream-like connections
- data BaseConnection = BaseConnection {}
- baseConnectionFromSocket :: Socket -> BaseConnection
- data Connection
- new :: IO () -> BaseConnection -> IO Connection
- newSTM :: IO () -> BaseConnection -> STM Connection
- forkWriterThread :: Connection -> IO ()
- forkInConnection :: Connection -> IO () -> IO ()
- close :: Connection -> IO ()
- write :: Connection -> ByteString -> STM ()
- writeAtLowWater :: Int -> Connection -> ByteString -> STM ()
- read :: Connection -> Int -> IO ByteString
- reada :: Connection -> Int -> IO ByteString
- pushBack :: Connection -> ByteString -> STM ()
Base connections
data BaseConnection Source
A BaseConnection abstracts a stream like connection.
Constructors
BaseConnection | |
Fields
|
baseConnectionFromSocket :: Socket -> BaseConnectionSource
Return a BaseConnection for the given socket.
Connection functions
data Connection Source
A Connection uses the functions from a BaseConnection and wraps them a number of commonly needed behaviours.
Firstly, a write queue is introduced so that writes can be non-blocking.
Secondly, the Connection can manage a number of threads. Almost always there will be a writer thread which is taking items from the write queue and writing them to the BaseConnection. In addition, there can be zero or more other threads managed by the Connection. If a thread which is managed dies, by throwing an exception or otherwise, it will close the connection and all other managed threads will be killed.
There is also the concept of pushing data back into the Connection. This is useful in a chain of reader functions where, for efficiency reasons, you would want to read large blocks at a time, but the data is self-deliminating so you would otherwise end up in a situation where you had read too much. See the pushBack function for details.
Arguments
:: IO () | the action to run when the connection closes |
-> BaseConnection | the socket-like object to make a connection from |
-> IO Connection |
Create a new Connection from a BaseConnection object
Arguments
:: IO () | the action run when the connection closes |
-> BaseConnection | the socket-like object to make a connection from |
-> STM Connection |
This creates most of a Connection, purely in the STM monad. The Connection returned from this must be passed to forkWriterThread, otherwise nothing will ever get written.
Arguments
:: Connection | the connection to fork the writer thread for |
-> IO () |
If you created the Connection in the STM monad using newSTM, you need to call this on it in order to create the thread which processes the outgoing queue.
Arguments
:: Connection | the connection to close on death |
-> IO () | the action to run |
-> IO () |
Run the given action, as if by forkIO, and manage the thread. If the given action completes or throws an exception, the connection will be closed and all other managed threads will be killed
close :: Connection -> IO ()Source
Close a connection
write :: Connection -> ByteString -> STM ()Source
Enqueue a ByteString to a connection. This does not block.
Arguments
:: Int | the max number of bytes in the queue before we enqueue anything |
-> Connection | the connection to write to |
-> ByteString | the data to enqueue |
-> STM () |
Block until the write queue has less than the given number of bytes in it then enqueue a new ByteString.
read :: Connection -> Int -> IO ByteStringSource
Read some number of bytes from a connection. The size is only a hint, the returned data may be shorter. A zero length read is EOF
reada :: Connection -> Int -> IO ByteStringSource
Read exactly a give number of bytes
pushBack :: Connection -> ByteString -> STM ()Source
Unread some amount of data. It will be returned in the next call to read.
The function pushes data to the front of the queue. Thus you need to push all the data base in one go, or the order of future reads will be wrong.
This might seem like an error, but consider the case of two actions: the first reads 20 bytes and pushs back the last 10 of them. The second reads 5 bytes and pushs back the last 4. If we appended to the push back queue the second action would put those 4 bytes after the remaining 5 from the first action.