@@ -101,7 +101,12 @@ data Aux = Persist (TBQueue Sequence) (TVar Sync)
101101data Context = Context {
102102 http2settings :: IORef Settings
103103 , streamTable :: StreamTable
104+ -- | Number of active streams initiated by the client; for enforcing our own
105+ -- max concurrency setting.
104106 , concurrency :: IORef Int
107+ -- | Number of active streams initiated by the server; for respecting the
108+ -- client's max concurrency setting.
109+ , pushConcurrency :: IORef Int
105110 -- | RFC 7540 says "Other frames (from any stream) MUST NOT
106111 -- occur between the HEADERS frame and any CONTINUATION
107112 -- frames that might follow". This field is used to implement
@@ -124,6 +129,7 @@ newContext :: IO Context
124129newContext = Context <$> newIORef defaultSettings
125130 <*> initialize 10 -- fixme: hard coding: 10
126131 <*> newIORef 0
132+ <*> newIORef 0
127133 <*> newIORef Nothing
128134 <*> newIORef 0
129135 <*> newIORef 2 -- first server push stream; 0 is reserved
@@ -193,28 +199,35 @@ data Stream = Stream {
193199 , streamBodyLength :: IORef Int
194200 , streamWindow :: TVar WindowSize
195201 , streamPriority :: IORef Priority
202+ -- | The concurrency IORef in which this stream has been counted. The client
203+ -- and server each have separate concurrency values to respect, so pushed
204+ -- streams need to decrement a different count when they're closed. This
205+ -- should be either @concurrency ctx@ or @pushConcurrency ctx@.
206+ , concurrencyRef :: IORef Int
196207 }
197208
198209instance Show Stream where
199210 show s = show (streamNumber s)
200211
201−newStream :: StreamId -> WindowSize -> IO Stream
202−newStream sid win = Stream sid <$> newIORef Idle
203− <*> newIORef Nothing
204− <*> newIORef 0
205− <*> newTVarIO win
206− <*> newIORef defaultPriority
212+newStream :: IORef Int -> StreamId -> WindowSize -> IO Stream
213+newStream ref sid win =
214+ Stream sid <$> newIORef Idle
215+ <*> newIORef Nothing
216+ <*> newIORef 0
217+ <*> newTVarIO win
218+ <*> newIORef defaultPriority
219+ <*> pure ref
207220
208221----------------------------------------------------------------
209222
210−opened :: Context -> Stream -> IO ()
211−opened Context{concurrency} Stream{streamState} = do
212− atomicModifyIORef' concurrency (\x -> (x+1,()))
223+opened :: Stream -> IO ()
224+opened Stream{concurrencyRef,streamState} = do
225+ atomicModifyIORef' concurrencyRef (\x -> (x+1,()))
213226 writeIORef streamState (Open JustOpened)
214227
215−closed :: Context -> Stream -> ClosedCode -> IO ()
216−closed Context{concurrency} Stream{streamState} cc = do
217− atomicModifyIORef' concurrency (\x -> (x-1,()))
228+closed :: Stream -> ClosedCode -> IO ()
229+closed Stream{concurrencyRef,streamState} cc = do
230+ atomicModifyIORef' concurrencyRef (\x -> (x-1,()))
218231 writeIORef streamState (Closed cc)
219232
220233----------------------------------------------------------------