    {-# LANGUAGE RecordWildCards #-}

    module Network.HTTP2.H2.StreamTable (
        -- * Types
        OddStreamTable (..),
        emptyOddStreamTable,
        EvenStreamTable (..),
        emptyEvenStreamTable,

        -- * Odd
        insertOdd,
        insertOdd',
        deleteOdd,
        lookupOdd,
        getOddConcurrency,
        getOddStreams,
        clearOddStreamTable,
        waitIncOdd,

        -- * Even
        insertEven,
        insertEven',
        deleteEven,
        lookupEven,
        getEvenConcurrency,
        clearEvenStreamTable,
        waitIncEven,
        insertEvenCache,
        deleteEvenCache,
        lookupEvenCache,
        getEvenStreams,
    ) where

    import Control.Concurrent
    import Control.Concurrent.STM
    import Control.Exception
    import Data.IntMap.Strict (IntMap)
    import qualified Data.IntMap.Strict as IntMap
    import Network.Control (LRUCache)
    import qualified Network.Control as LRUCache

    import Imports
    import Network.HTTP2.H2.Types (Stream (..))

    ----------------------------------------------------------------

    data OddStreamTable = OddStreamTable
        { OddStreamTable -> Int
    oddConc :: Int
        , OddStreamTable -> IntMap Stream
    oddTable :: IntMap Stream
        }

    emptyOddStreamTable :: OddStreamTable
    emptyOddStreamTable :: OddStreamTable
    emptyOddStreamTable = Int -> IntMap Stream -> OddStreamTable
    OddStreamTable Int
    0 IntMap Stream
    forall a. IntMap a
    IntMap.empty

    data EvenStreamTable = EvenStreamTable
        { EvenStreamTable -> Int
    evenConc :: Int
        , EvenStreamTable -> IntMap Stream
    evenTable :: IntMap Stream
        , -- Cache must contain Stream instead of StreamId because
          -- a Stream is deleted when end-of-stream is received.
          -- After that, cache is looked up.
          -- LRUCache is not used as LRU but as fixed-size map.
          EvenStreamTable -> LRUCache (Method, Method) Stream
    evenCache :: LRUCache (Method, ByteString) Stream
        }

    emptyEvenStreamTable :: Int -> EvenStreamTable
    emptyEvenStreamTable :: Int -> EvenStreamTable
    emptyEvenStreamTable Int
    lim = Int
    -> IntMap Stream
    -> LRUCache (Method, Method) Stream
    -> EvenStreamTable
    EvenStreamTable Int
    0 IntMap Stream
    forall a. IntMap a
    IntMap.empty (LRUCache (Method, Method) Stream -> EvenStreamTable)
    -> LRUCache (Method, Method) Stream -> EvenStreamTable
    forall a b. (a -> b) -> a -> b
    $ Int -> LRUCache (Method, Method) Stream
    forall k v. Int -> LRUCache k v
    LRUCache.empty Int
    lim

    ----------------------------------------------------------------

    insertOdd :: TVar OddStreamTable -> IntMap.Key -> Stream -> IO ()
    insertOdd :: TVar OddStreamTable -> Int -> Stream -> IO ()
    insertOdd TVar OddStreamTable
    var Int
    k Stream
    v = STM () -> IO ()
    forall a. STM a -> IO a
    atomically (STM () -> IO ()) -> STM () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ TVar OddStreamTable -> (OddStreamTable -> OddStreamTable) -> STM ()
    forall a. TVar a -> (a -> a) -> STM ()
    modifyTVar TVar OddStreamTable
    var ((OddStreamTable -> OddStreamTable) -> STM ())
    -> (OddStreamTable -> OddStreamTable) -> STM ()
    forall a b. (a -> b) -> a -> b
    $ \OddStreamTable{Int
    IntMap Stream
    oddConc :: OddStreamTable -> Int
    oddTable :: OddStreamTable -> IntMap Stream
    oddConc :: Int
    oddTable :: IntMap Stream
    ..} ->
        let oddConc' :: Int
    oddConc' = Int
    oddConc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
            oddTable' :: IntMap Stream
    oddTable' = Int -> Stream -> IntMap Stream -> IntMap Stream
    forall a. Int -> a -> IntMap a -> IntMap a
    IntMap.insert Int
    k Stream
    v IntMap Stream
    oddTable
         in Int -> IntMap Stream -> OddStreamTable
    OddStreamTable Int
    oddConc' IntMap Stream
    oddTable'

    insertOdd' :: TVar OddStreamTable -> IntMap.Key -> Stream -> IO ()
    insertOdd' :: TVar OddStreamTable -> Int -> Stream -> IO ()
    insertOdd' TVar OddStreamTable
    var Int
    k Stream
    v = STM () -> IO ()
    forall a. STM a -> IO a
    atomically (STM () -> IO ()) -> STM () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ TVar OddStreamTable -> (OddStreamTable -> OddStreamTable) -> STM ()
    forall a. TVar a -> (a -> a) -> STM ()
    modifyTVar TVar OddStreamTable
    var ((OddStreamTable -> OddStreamTable) -> STM ())
    -> (OddStreamTable -> OddStreamTable) -> STM ()
    forall a b. (a -> b) -> a -> b
    $ \OddStreamTable{Int
    IntMap Stream
    oddConc :: OddStreamTable -> Int
    oddTable :: OddStreamTable -> IntMap Stream
    oddConc :: Int
    oddTable :: IntMap Stream
    ..} ->
        let oddTable' :: IntMap Stream
    oddTable' = Int -> Stream -> IntMap Stream -> IntMap Stream
    forall a. Int -> a -> IntMap a -> IntMap a
    IntMap.insert Int
    k Stream
    v IntMap Stream
    oddTable
         in Int -> IntMap Stream -> OddStreamTable
    OddStreamTable Int
    oddConc IntMap Stream
    oddTable'

    deleteOdd :: TVar OddStreamTable -> IntMap.Key -> SomeException -> IO ()
    deleteOdd :: TVar OddStreamTable -> Int -> SomeException -> IO ()
    deleteOdd TVar OddStreamTable
    var Int
    k SomeException
    err = do
        mv <- STM (Maybe Stream) -> IO (Maybe Stream)
    forall a. STM a -> IO a
    atomically STM (Maybe Stream)
    deleteStream
        case mv of
            Maybe Stream
    Nothing -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- Stream was already removed
            Just Stream
    v -> IO Bool -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO Bool -> IO ())
    -> (Either SomeException InpObj -> IO Bool)
    -> Either SomeException InpObj
    -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . MVar (Either SomeException InpObj)
    -> Either SomeException InpObj -> IO Bool
    forall a. MVar a -> a -> IO Bool
    tryPutMVar (Stream -> MVar (Either SomeException InpObj)
    streamInput Stream
    v) (Either SomeException InpObj -> IO ())
    -> Either SomeException InpObj -> IO ()
    forall a b. (a -> b) -> a -> b
    $ SomeException -> Either SomeException InpObj
    forall a b. a -> Either a b
    Left SomeException
    err
      where
        deleteStream :: STM (Maybe Stream)
        deleteStream :: STM (Maybe Stream)
    deleteStream = do
            OddStreamTable{..} <- TVar OddStreamTable -> STM OddStreamTable
    forall a. TVar a -> STM a
    readTVar TVar OddStreamTable
    var
            let oddConc' = Int
    oddConc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
                oddTable' = Int -> IntMap Stream -> IntMap Stream
    forall a. Int -> IntMap a -> IntMap a
    IntMap.delete Int
    k IntMap Stream
    oddTable
            writeTVar var $ OddStreamTable oddConc' oddTable'
            return $ IntMap.lookup k oddTable

    lookupOdd :: TVar OddStreamTable -> IntMap.Key -> IO (Maybe Stream)
    lookupOdd :: TVar OddStreamTable -> Int -> IO (Maybe Stream)
    lookupOdd TVar OddStreamTable
    var Int
    k = Int -> IntMap Stream -> Maybe Stream
    forall a. Int -> IntMap a -> Maybe a
    IntMap.lookup Int
    k (IntMap Stream -> Maybe Stream)
    -> (OddStreamTable -> IntMap Stream)
    -> OddStreamTable
    -> Maybe Stream
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . OddStreamTable -> IntMap Stream
    oddTable (OddStreamTable -> Maybe Stream)
    -> IO OddStreamTable -> IO (Maybe Stream)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> TVar OddStreamTable -> IO OddStreamTable
    forall a. TVar a -> IO a
    readTVarIO TVar OddStreamTable
    var

    getOddConcurrency :: TVar OddStreamTable -> IO Int
    getOddConcurrency :: TVar OddStreamTable -> IO Int
    getOddConcurrency TVar OddStreamTable
    var = OddStreamTable -> Int
    oddConc (OddStreamTable -> Int) -> IO OddStreamTable -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> TVar OddStreamTable -> IO OddStreamTable
    forall a. TVar a -> IO a
    readTVarIO TVar OddStreamTable
    var

    getOddStreams :: TVar OddStreamTable -> IO (IntMap Stream)
    getOddStreams :: TVar OddStreamTable -> IO (IntMap Stream)
    getOddStreams TVar OddStreamTable
    var = OddStreamTable -> IntMap Stream
    oddTable (OddStreamTable -> IntMap Stream)
    -> IO OddStreamTable -> IO (IntMap Stream)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> TVar OddStreamTable -> IO OddStreamTable
    forall a. TVar a -> IO a
    readTVarIO TVar OddStreamTable
    var

    clearOddStreamTable :: TVar OddStreamTable -> IO (IntMap Stream)
    clearOddStreamTable :: TVar OddStreamTable -> IO (IntMap Stream)
    clearOddStreamTable TVar OddStreamTable
    var = STM (IntMap Stream) -> IO (IntMap Stream)
    forall a. STM a -> IO a
    atomically (STM (IntMap Stream) -> IO (IntMap Stream))
    -> STM (IntMap Stream) -> IO (IntMap Stream)
    forall a b. (a -> b) -> a -> b
    $ do
        OddStreamTable{..} <- TVar OddStreamTable -> STM OddStreamTable
    forall a. TVar a -> STM a
    readTVar TVar OddStreamTable
    var
        writeTVar var emptyOddStreamTable
        return oddTable

    waitIncOdd :: TVar OddStreamTable -> Int -> STM ()
    waitIncOdd :: TVar OddStreamTable -> Int -> STM ()
    waitIncOdd TVar OddStreamTable
    var Int
    maxConc = do
        OddStreamTable{..} <- TVar OddStreamTable -> STM OddStreamTable
    forall a. TVar a -> STM a
    readTVar TVar OddStreamTable
    var
        check (oddConc < maxConc)
        let oddConc' = Int
    oddConc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
        writeTVar var $ OddStreamTable oddConc' oddTable

    ----------------------------------------------------------------

    insertEven :: TVar EvenStreamTable -> IntMap.Key -> Stream -> IO ()
    insertEven :: TVar EvenStreamTable -> Int -> Stream -> IO ()
    insertEven TVar EvenStreamTable
    var Int
    k Stream
    v = STM () -> IO ()
    forall a. STM a -> IO a
    atomically (STM () -> IO ()) -> STM () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ TVar EvenStreamTable
    -> (EvenStreamTable -> EvenStreamTable) -> STM ()
    forall a. TVar a -> (a -> a) -> STM ()
    modifyTVar TVar EvenStreamTable
    var ((EvenStreamTable -> EvenStreamTable) -> STM ())
    -> (EvenStreamTable -> EvenStreamTable) -> STM ()
    forall a b. (a -> b) -> a -> b
    $ \EvenStreamTable{Int
    IntMap Stream
    LRUCache (Method, Method) Stream
    evenConc :: EvenStreamTable -> Int
    evenTable :: EvenStreamTable -> IntMap Stream
    evenCache :: EvenStreamTable -> LRUCache (Method, Method) Stream
    evenConc :: Int
    evenTable :: IntMap Stream
    evenCache :: LRUCache (Method, Method) Stream
    ..} ->
        let evenConc' :: Int
    evenConc' = Int
    evenConc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
            evenTable' :: IntMap Stream
    evenTable' = Int -> Stream -> IntMap Stream -> IntMap Stream
    forall a. Int -> a -> IntMap a -> IntMap a
    IntMap.insert Int
    k Stream
    v IntMap Stream
    evenTable
         in Int
    -> IntMap Stream
    -> LRUCache (Method, Method) Stream
    -> EvenStreamTable
    EvenStreamTable Int
    evenConc' IntMap Stream
    evenTable' LRUCache (Method, Method) Stream
    evenCache

    insertEven' :: TVar EvenStreamTable -> IntMap.Key -> Stream -> IO ()
    insertEven' :: TVar EvenStreamTable -> Int -> Stream -> IO ()
    insertEven' TVar EvenStreamTable
    var Int
    k Stream
    v = STM () -> IO ()
    forall a. STM a -> IO a
    atomically (STM () -> IO ()) -> STM () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ TVar EvenStreamTable
    -> (EvenStreamTable -> EvenStreamTable) -> STM ()
    forall a. TVar a -> (a -> a) -> STM ()
    modifyTVar TVar EvenStreamTable
    var ((EvenStreamTable -> EvenStreamTable) -> STM ())
    -> (EvenStreamTable -> EvenStreamTable) -> STM ()
    forall a b. (a -> b) -> a -> b
    $ \EvenStreamTable{Int
    IntMap Stream
    LRUCache (Method, Method) Stream
    evenConc :: EvenStreamTable -> Int
    evenTable :: EvenStreamTable -> IntMap Stream
    evenCache :: EvenStreamTable -> LRUCache (Method, Method) Stream
    evenConc :: Int
    evenTable :: IntMap Stream
    evenCache :: LRUCache (Method, Method) Stream
    ..} ->
        let evenTable' :: IntMap Stream
    evenTable' = Int -> Stream -> IntMap Stream -> IntMap Stream
    forall a. Int -> a -> IntMap a -> IntMap a
    IntMap.insert Int
    k Stream
    v IntMap Stream
    evenTable
         in Int
    -> IntMap Stream
    -> LRUCache (Method, Method) Stream
    -> EvenStreamTable
    EvenStreamTable Int
    evenConc IntMap Stream
    evenTable' LRUCache (Method, Method) Stream
    evenCache

    deleteEven :: TVar EvenStreamTable -> IntMap.Key -> SomeException -> IO ()
    deleteEven :: TVar EvenStreamTable -> Int -> SomeException -> IO ()
    deleteEven TVar EvenStreamTable
    var Int
    k SomeException
    err = do
        mv <- STM (Maybe Stream) -> IO (Maybe Stream)
    forall a. STM a -> IO a
    atomically STM (Maybe Stream)
    deleteStream
        case mv of
            Maybe Stream
    Nothing -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- Stream was already removed
            Just Stream
    v -> IO Bool -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO Bool -> IO ())
    -> (Either SomeException InpObj -> IO Bool)
    -> Either SomeException InpObj
    -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . MVar (Either SomeException InpObj)
    -> Either SomeException InpObj -> IO Bool
    forall a. MVar a -> a -> IO Bool
    tryPutMVar (Stream -> MVar (Either SomeException InpObj)
    streamInput Stream
    v) (Either SomeException InpObj -> IO ())
    -> Either SomeException InpObj -> IO ()
    forall a b. (a -> b) -> a -> b
    $ SomeException -> Either SomeException InpObj
    forall a b. a -> Either a b
    Left SomeException
    err
      where
        deleteStream :: STM (Maybe Stream)
        deleteStream :: STM (Maybe Stream)
    deleteStream = do
            EvenStreamTable{..} <- TVar EvenStreamTable -> STM EvenStreamTable
    forall a. TVar a -> STM a
    readTVar TVar EvenStreamTable
    var
            let evenConc' = Int
    evenConc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
                evenTable' = Int -> IntMap Stream -> IntMap Stream
    forall a. Int -> IntMap a -> IntMap a
    IntMap.delete Int
    k IntMap Stream
    evenTable
            writeTVar var $ EvenStreamTable evenConc' evenTable' evenCache
            return $ IntMap.lookup k evenTable

    lookupEven :: TVar EvenStreamTable -> IntMap.Key -> IO (Maybe Stream)
    lookupEven :: TVar EvenStreamTable -> Int -> IO (Maybe Stream)
    lookupEven TVar EvenStreamTable
    var Int
    k = Int -> IntMap Stream -> Maybe Stream
    forall a. Int -> IntMap a -> Maybe a
    IntMap.lookup Int
    k (IntMap Stream -> Maybe Stream)
    -> (EvenStreamTable -> IntMap Stream)
    -> EvenStreamTable
    -> Maybe Stream
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EvenStreamTable -> IntMap Stream
    evenTable (EvenStreamTable -> Maybe Stream)
    -> IO EvenStreamTable -> IO (Maybe Stream)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> TVar EvenStreamTable -> IO EvenStreamTable
    forall a. TVar a -> IO a
    readTVarIO TVar EvenStreamTable
    var

    getEvenConcurrency :: TVar EvenStreamTable -> IO Int
    getEvenConcurrency :: TVar EvenStreamTable -> IO Int
    getEvenConcurrency TVar EvenStreamTable
    var = EvenStreamTable -> Int
    evenConc (EvenStreamTable -> Int) -> IO EvenStreamTable -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> TVar EvenStreamTable -> IO EvenStreamTable
    forall a. TVar a -> IO a
    readTVarIO TVar EvenStreamTable
    var

    clearEvenStreamTable :: TVar EvenStreamTable -> IO (IntMap Stream)
    clearEvenStreamTable :: TVar EvenStreamTable -> IO (IntMap Stream)
    clearEvenStreamTable TVar EvenStreamTable
    var = STM (IntMap Stream) -> IO (IntMap Stream)
    forall a. STM a -> IO a
    atomically (STM (IntMap Stream) -> IO (IntMap Stream))
    -> STM (IntMap Stream) -> IO (IntMap Stream)
    forall a b. (a -> b) -> a -> b
    $ do
        EvenStreamTable{..} <- TVar EvenStreamTable -> STM EvenStreamTable
    forall a. TVar a -> STM a
    readTVar TVar EvenStreamTable
    var
        writeTVar var $ emptyEvenStreamTable 0
        return evenTable

    waitIncEven :: TVar EvenStreamTable -> Int -> STM ()
    waitIncEven :: TVar EvenStreamTable -> Int -> STM ()
    waitIncEven TVar EvenStreamTable
    var Int
    maxConc = do
        EvenStreamTable{..} <- TVar EvenStreamTable -> STM EvenStreamTable
    forall a. TVar a -> STM a
    readTVar TVar EvenStreamTable
    var
        check (evenConc < maxConc)
        let evenConc' = Int
    evenConc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
        writeTVar var $ EvenStreamTable evenConc' evenTable evenCache

    insertEvenCache
        :: TVar EvenStreamTable -> Method -> ByteString -> Stream -> IO ()
    insertEvenCache :: TVar EvenStreamTable -> Method -> Method -> Stream -> IO ()
    insertEvenCache TVar EvenStreamTable
    var Method
    method Method
    path strm :: Stream
    strm@Stream{Int
    TVar TxFlow
    MVar (Either SomeException InpObj)
    IORef (Maybe RxQ)
    IORef RxFlow
    IORef StreamState
    streamInput :: Stream -> MVar (Either SomeException InpObj)
    streamNumber :: Int
    streamState :: IORef StreamState
    streamInput :: MVar (Either SomeException InpObj)
    streamTxFlow :: TVar TxFlow
    streamRxFlow :: IORef RxFlow
    streamRxQ :: IORef (Maybe RxQ)
    streamRxQ :: Stream -> IORef (Maybe RxQ)
    streamRxFlow :: Stream -> IORef RxFlow
    streamTxFlow :: Stream -> TVar TxFlow
    streamState :: Stream -> IORef StreamState
    streamNumber :: Stream -> Int
    ..} = STM () -> IO ()
    forall a. STM a -> IO a
    atomically (STM () -> IO ()) -> STM () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ TVar EvenStreamTable
    -> (EvenStreamTable -> EvenStreamTable) -> STM ()
    forall a. TVar a -> (a -> a) -> STM ()
    modifyTVar TVar EvenStreamTable
    var ((EvenStreamTable -> EvenStreamTable) -> STM ())
    -> (EvenStreamTable -> EvenStreamTable) -> STM ()
    forall a b. (a -> b) -> a -> b
    $ \EvenStreamTable{Int
    IntMap Stream
    LRUCache (Method, Method) Stream
    evenConc :: EvenStreamTable -> Int
    evenTable :: EvenStreamTable -> IntMap Stream
    evenCache :: EvenStreamTable -> LRUCache (Method, Method) Stream
    evenConc :: Int
    evenTable :: IntMap Stream
    evenCache :: LRUCache (Method, Method) Stream
    ..} ->
        let evenConc' :: Int
    evenConc' = Int
    evenConc Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
            evenTable' :: IntMap Stream
    evenTable' = Int -> Stream -> IntMap Stream -> IntMap Stream
    forall a. Int -> a -> IntMap a -> IntMap a
    IntMap.insert Int
    streamNumber Stream
    strm IntMap Stream
    evenTable
            evenCache' :: LRUCache (Method, Method) Stream
    evenCache' = (Method, Method)
    -> Stream
    -> LRUCache (Method, Method) Stream
    -> LRUCache (Method, Method) Stream
    forall k v. Ord k => k -> v -> LRUCache k v -> LRUCache k v
    LRUCache.insert (Method
    method, Method
    path) Stream
    strm LRUCache (Method, Method) Stream
    evenCache
         in Int
    -> IntMap Stream
    -> LRUCache (Method, Method) Stream
    -> EvenStreamTable
    EvenStreamTable Int
    evenConc' IntMap Stream
    evenTable' LRUCache (Method, Method) Stream
    evenCache'

    deleteEvenCache :: TVar EvenStreamTable -> Method -> ByteString -> IO ()
    deleteEvenCache :: TVar EvenStreamTable -> Method -> Method -> IO ()
    deleteEvenCache TVar EvenStreamTable
    var Method
    m Method
    path = STM () -> IO ()
    forall a. STM a -> IO a
    atomically (STM () -> IO ()) -> STM () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ TVar EvenStreamTable
    -> (EvenStreamTable -> EvenStreamTable) -> STM ()
    forall a. TVar a -> (a -> a) -> STM ()
    modifyTVar TVar EvenStreamTable
    var ((EvenStreamTable -> EvenStreamTable) -> STM ())
    -> (EvenStreamTable -> EvenStreamTable) -> STM ()
    forall a b. (a -> b) -> a -> b
    $ \EvenStreamTable{Int
    IntMap Stream
    LRUCache (Method, Method) Stream
    evenConc :: EvenStreamTable -> Int
    evenTable :: EvenStreamTable -> IntMap Stream
    evenCache :: EvenStreamTable -> LRUCache (Method, Method) Stream
    evenConc :: Int
    evenTable :: IntMap Stream
    evenCache :: LRUCache (Method, Method) Stream
    ..} ->
        let evenCache' :: LRUCache (Method, Method) Stream
    evenCache' = (Method, Method)
    -> LRUCache (Method, Method) Stream
    -> LRUCache (Method, Method) Stream
    forall k v. Ord k => k -> LRUCache k v -> LRUCache k v
    LRUCache.delete (Method
    m, Method
    path) LRUCache (Method, Method) Stream
    evenCache
         in Int
    -> IntMap Stream
    -> LRUCache (Method, Method) Stream
    -> EvenStreamTable
    EvenStreamTable Int
    evenConc IntMap Stream
    evenTable LRUCache (Method, Method) Stream
    evenCache'

    lookupEvenCache
        :: TVar EvenStreamTable -> Method -> ByteString -> IO (Maybe Stream)
    lookupEvenCache :: TVar EvenStreamTable -> Method -> Method -> IO (Maybe Stream)
    lookupEvenCache TVar EvenStreamTable
    var Method
    m Method
    path = (Method, Method)
    -> LRUCache (Method, Method) Stream -> Maybe Stream
    forall k v. Ord k => k -> LRUCache k v -> Maybe v
    LRUCache.lookup (Method
    m, Method
    path) (LRUCache (Method, Method) Stream -> Maybe Stream)
    -> (EvenStreamTable -> LRUCache (Method, Method) Stream)
    -> EvenStreamTable
    -> Maybe Stream
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EvenStreamTable -> LRUCache (Method, Method) Stream
    evenCache (EvenStreamTable -> Maybe Stream)
    -> IO EvenStreamTable -> IO (Maybe Stream)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> TVar EvenStreamTable -> IO EvenStreamTable
    forall a. TVar a -> IO a
    readTVarIO TVar EvenStreamTable
    var

    getEvenStreams :: TVar EvenStreamTable -> IO (IntMap Stream)
    getEvenStreams :: TVar EvenStreamTable -> IO (IntMap Stream)
    getEvenStreams TVar EvenStreamTable
    var = EvenStreamTable -> IntMap Stream
    evenTable (EvenStreamTable -> IntMap Stream)
    -> IO EvenStreamTable -> IO (IntMap Stream)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> TVar EvenStreamTable -> IO EvenStreamTable
    forall a. TVar a -> IO a
    readTVarIO TVar EvenStreamTable
    var