Skip to content

Commit

Permalink
Inefficient handling of the message queue and selective receive for u…
Browse files Browse the repository at this point in the history
…ntimed_stream_loop_send fixed by Martin Bjorklund.
  • Loading branch information
Claes Wikstrom committed Dec 17, 2013
1 parent 0043df3 commit f29005b
Showing 1 changed file with 19 additions and 58 deletions.
77 changes: 19 additions & 58 deletions src/yaws_server.erl
Expand Up @@ -2903,72 +2903,33 @@ deliver_dyn_file(CliSock, _Bin, [], ARG,_UT,_N) ->
finish_up_dyn_file(ARG, CliSock).


stream_loop_send(Priv, CliSock, Timeout) ->
{ok, FlushTimer} = timer:send_after(300, flush_timer),
case Timeout of
infinity ->
untimed_stream_loop_send(Priv, CliSock, FlushTimer);
_ ->
{ok, TimeoutTimer} = timer:send_after(Timeout, timeout_timer),
stream_loop_send(Priv, CliSock, Timeout,
FlushTimer, TimeoutTimer)
end.
-define(unflushed_timeout, 300).

untimed_stream_loop_send(Priv, CliSock, FlushTimer) ->
receive
{streamcontent, Cont} ->
P = send_streamcontent_chunk(Priv, CliSock, Cont),
untimed_stream_loop_send(P, CliSock, FlushTimer) ;
{streamcontent_with_ack, From, Cont} -> % acknowledge after send
P = send_streamcontent_chunk(Priv, CliSock, Cont),
From ! {self(), streamcontent_ack},
untimed_stream_loop_send(P, CliSock, FlushTimer) ;
endofstreamcontent ->
cancel_t(FlushTimer, flush_timer),
end_streaming(Priv, CliSock);
timeout_timer ->
cancel_t(FlushTimer, flush_timer),
erlang:error(stream_timeout);
flush_timer ->
P = sync_streamcontent(Priv, CliSock),
untimed_stream_loop_send(P, CliSock, FlushTimer)
end.
stream_loop_send(Priv, CliSock, IdleTimeout) ->
stream_loop_send(Priv, CliSock, unflushed, ?unflushed_timeout, IdleTimeout).

cancel_t(T, Msg) ->
timer:cancel(T),
receive
Msg -> ok
after 0 -> ok
end.

stream_loop_send(Priv, CliSock, Timeout,
FlushTimer, TimeoutTimer) ->
stream_loop_send(Priv, CliSock, FlushStatus, CurTimeout, IdleTimeout) ->
receive
{streamcontent, Cont} ->
P = send_streamcontent_chunk(Priv, CliSock, Cont),
cancel_t(TimeoutTimer, timeout_timer),
{ok, TimeoutTimer2} = timer:send_after(Timeout, timeout_timer),
stream_loop_send(P, CliSock, Timeout,
FlushTimer, TimeoutTimer2) ;
{streamcontent_with_ack, From, Cont} -> % acknowledge after send
stream_loop_send(P, CliSock, unflushed,
?unflushed_timeout, IdleTimeout);
{streamcontent_with_ack, From, Cont} -> % acknowledge after send
P = send_streamcontent_chunk(Priv, CliSock, Cont),
From ! {self(), streamcontent_ack},
cancel_t(TimeoutTimer, timeout_timer),
{ok, TimeoutTimer2} = timer:send_after(Timeout, timeout_timer),
stream_loop_send(P, CliSock, Timeout,
FlushTimer, TimeoutTimer2) ;
stream_loop_send(P, CliSock, unflushed,
?unflushed_timeout, IdleTimeout);
endofstreamcontent ->
cancel_t(TimeoutTimer, timeout_timer),
cancel_t(FlushTimer, flush_timer),
end_streaming(Priv, CliSock);
timeout_timer ->
cancel_t(TimeoutTimer, timeout_timer),
cancel_t(FlushTimer, flush_timer),
erlang:error(stream_timeout);
flush_timer ->
P = sync_streamcontent(Priv, CliSock),
stream_loop_send(P, CliSock, Timeout,
FlushTimer, TimeoutTimer)
end_streaming(Priv, CliSock)
after CurTimeout ->
case FlushStatus of
flushed ->
erlang:error(stream_timeout);
unflushed ->
P = sync_streamcontent(Priv, CliSock),
stream_loop_send(P, CliSock, flushed,
IdleTimeout, IdleTimeout)
end
end.

make_chunk(Data) ->
Expand Down

0 comments on commit f29005b

Please sign in to comment.