@@ -58,22 +58,15 @@ unlessClosed ctx
5858 let rst = resetFrame InternalError streamNumber
5959 connSendAll rst
6060
61−checkWindowSize :: TVar WindowSize -> TVar WindowSize -> PriorityTree Output -> Output -> Priority -> (WindowSize -> IO ()) -> IO ()
62−checkWindowSize connWindow strmWindow outQ out pri body = do
61+checkWindowSize :: TVar WindowSize -> TVar WindowSize -> (WindowSize -> IO ()) -> IO ()
62+checkWindowSize connWindow strmWindow body = do
6363 cw <- atomically $ do
6464 w <- readTVar connWindow
6565 check (w > 0)
6666 return w
67+ -- sw is greater than 0
6768 sw <- atomically $ readTVar strmWindow
68− if sw == 0 then
69− void $ forkIO $ do
70− -- checkme: if connection is closed? GC throws dead lock error?
71− atomically $ do
72− x <- readTVar strmWindow
73− check (x > 0)
74− enqueue outQ out pri
75− else
76− body (min cw sw)
69+ body (min cw sw)
7770
7871frameSender :: Context -> Connection -> InternalInfo -> S.Settings -> IO ()
7972frameSender ctx@Context{outputQ,connectionWindow}
@@ -100,9 +93,8 @@ frameSender ctx@Context{outputQ,connectionWindow}
10093 switch (OFrame frame) = do
10194 connSendAll frame
10295 loop
103− switch out@(OResponse strm rsp aux) = unlessClosed ctx conn strm $ do
104− pri <- readIORef $ streamPriority strm
105− checkWindowSize connectionWindow (streamWindow strm) outputQ out pri $ \lim -> do
96+ switch (OResponse strm rsp aux) = unlessClosed ctx conn strm $ do
97+ checkWindowSize connectionWindow (streamWindow strm) $ \lim -> do
10698 -- Header frame and Continuation frame
10799 let sid = streamNumber strm
108100 endOfStream = case aux of
@@ -118,7 +110,7 @@ frameSender ctx@Context{outputQ,connectionWindow}
118110 Next datPayloadLen mnext <-
119111 fillResponseBodyGetNext conn ii payloadOff lim rsp
120112 fillDataHeaderSend strm total datPayloadLen mnext
121− maybeEnqueueNext strm mnext pri
113+ maybeEnqueueNext strm mnext
122114 Oneshot False -> do
123115 -- "closed" must be before "connSendAll". If not,
124116 -- the context would be switched to the receiver,
@@ -129,22 +121,21 @@ frameSender ctx@Context{outputQ,connectionWindow}
129121 (off, needSend) <- sendHeadersIfNecessary total
130122 let payloadOff = off + frameHeaderLength
131123 Next datPayloadLen mnext <-
132− fillStreamBodyGetNext conn payloadOff lim sq tvar
124+ fillStreamBodyGetNext conn payloadOff lim sq tvar strm
133125 -- If no data was immediately available, avoid sending an
134126 -- empty data frame.
135127 if datPayloadLen > 0 then
136128 fillDataHeaderSend strm total datPayloadLen mnext
137129 else
138130 when needSend $ flushN off
139− maybeEnqueueNext strm mnext pri
131+ maybeEnqueueNext strm mnext
140132 loop
141− switch out@(ONext strm curr) = unlessClosed ctx conn strm $ do
142− pri <- readIORef $ streamPriority strm
143− checkWindowSize connectionWindow (streamWindow strm) outputQ out pri $ \lim -> do
133+ switch (ONext strm curr) = unlessClosed ctx conn strm $ do
134+ checkWindowSize connectionWindow (streamWindow strm) $ \lim -> do
144135 -- Data frame payload
145136 Next datPayloadLen mnext <- curr lim
146137 fillDataHeaderSend strm 0 datPayloadLen mnext
147− maybeEnqueueNext strm mnext pri
138+ maybeEnqueueNext strm mnext
148139 loop
149140
150141 -- Flush the connection buffer to the socket, where the first 'n' bytes of
@@ -189,9 +180,16 @@ frameSender ctx@Context{outputQ,connectionWindow}
189180 -- available; do nothing otherwise. If the stream is not finished, it must
190181 -- already have been written to the 'TVar' owned by 'waiter', which will
191182 -- put it back into the queue when more output becomes available.
192− maybeEnqueueNext :: Stream -> Control DynaNext -> Priority -> IO ()
193− maybeEnqueueNext strm (CNext next) = enqueue outputQ (ONext strm next)
194− maybeEnqueueNext _ _ = const $ return ()
183+ maybeEnqueueNext :: Stream -> Control DynaNext -> IO ()
184+ maybeEnqueueNext strm (CNext next) = do
185+ let out = ONext strm next
186+ sw <- atomically $ readTVar $ streamWindow strm
187+ if sw == 0 then
188+ void $ forkIO $ enqueueWhenWindowIsOpen outputQ out
189+ else do
190+ pri <- readIORef $ streamPriority strm
191+ enqueue outputQ out pri
192+ maybeEnqueueNext _ _ = return ()
195193
196194
197195 -- Send headers if there is not room for a 1-byte data frame, and return
@@ -285,13 +283,13 @@ fileStartEnd _ (Just part) =
285283
286284----------------------------------------------------------------
287285
288−fillStreamBodyGetNext :: Connection -> Int -> WindowSize -> TBQueue Sequence -> TVar Sync -> IO Next
286+fillStreamBodyGetNext :: Connection -> Int -> WindowSize -> TBQueue Sequence -> TVar Sync -> Stream -> IO Next
289287fillStreamBodyGetNext Connection{connWriteBuffer,connBufferSize}
290− off lim sq tvar = do
288+ off lim sq tvar strm = do
291289 let datBuf = connWriteBuffer `plusPtr` off
292290 room = min (connBufferSize - off) lim
293291 (leftover, cont, len) <- runStreamBuilder datBuf room sq
294− nextForStream connWriteBuffer connBufferSize sq tvar leftover cont len
292+ nextForStream connWriteBuffer connBufferSize sq tvar strm leftover cont len
295293
296294----------------------------------------------------------------
297295
@@ -345,8 +343,8 @@ runStreamBuilder buf0 room0 sq = loop buf0 room0 0
345343 Just SFlush -> return (LZero, True, total)
346344 Just SFinish -> return (LZero, False, total)
347345
348−fillBufStream :: Buffer -> BufSize -> Leftover -> TBQueue Sequence -> TVar Sync -> DynaNext
349−fillBufStream buf0 siz0 leftover0 sq tvar lim0 = do
346+fillBufStream :: Buffer -> BufSize -> Leftover -> TBQueue Sequence -> TVar Sync -> Stream -> DynaNext
347+fillBufStream buf0 siz0 leftover0 sq tvar strm lim0 = do
350348 let payloadBuf = buf0 `plusPtr` frameHeaderLength
351349 room0 = min (siz0 - frameHeaderLength) lim0
352350 case leftover0 of
@@ -364,7 +362,7 @@ fillBufStream buf0 siz0 leftover0 sq tvar lim0 = do
364362 void $ copy payloadBuf bs1
365363 getNext (LTwo bs2 writer) True room0
366364 where
367− getNext = nextForStream buf0 siz0 sq tvar
365+ getNext = nextForStream buf0 siz0 sq tvar strm
368366 write writer1 buf room sofar = do
369367 (len, signal) <- writer1 buf room
370368 case signal of
@@ -379,17 +377,18 @@ fillBufStream buf0 siz0 leftover0 sq tvar lim0 = do
379377 let !total = sofar + len
380378 getNext (LTwo bs writer) True total
381379
382−nextForStream :: Buffer -> BufSize -> TBQueue Sequence -> TVar Sync
380+nextForStream :: Buffer -> BufSize -> TBQueue Sequence -> TVar Sync -> Stream
383381 -> Leftover -> Bool -> BytesFilled
384382 -> IO Next
385−nextForStream _ _ _ tvar _ False len = do
383+nextForStream _ _ _ tvar _ _ False len = do
386384 atomically $ writeTVar tvar SyncFinish
387385 return $ Next len CFinish
388−nextForStream buf siz sq tvar LZero True len = do
389− atomically $ writeTVar tvar $ SyncNext (fillBufStream buf siz LZero sq tvar)
386+nextForStream buf siz sq tvar strm LZero True len = do
387+ let out = ONext strm (fillBufStream buf siz LZero sq tvar strm)
388+ atomically $ writeTVar tvar $ SyncNext out
390389 return $ Next len CNone
391−nextForStream buf siz sq tvar leftover True len =
392− return $ Next len (CNext (fillBufStream buf siz leftover sq tvar))
390+nextForStream buf siz sq tvar strm leftover True len =
391+ return $ Next len (CNext (fillBufStream buf siz leftover sq tvar strm))
393392
394393----------------------------------------------------------------
395394