diff options
author | Loïc Hoguin <[email protected]> | 2012-01-31 09:45:44 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2012-01-31 09:45:44 +0100 |
commit | 21802d2767e48924186d173eb36b61994e990b87 (patch) | |
tree | c65430ed9a6b7d9f590592529833bae64ecee11a | |
parent | 42bf0ea57d1a5db77027a66d72a59d0049a54123 (diff) | |
download | cowboy-21802d2767e48924186d173eb36b61994e990b87.tar.gz cowboy-21802d2767e48924186d173eb36b61994e990b87.tar.bz2 cowboy-21802d2767e48924186d173eb36b61994e990b87.zip |
Use queue() for managing wait queues in cowboy_listener
The previous solution was retrieving the last put connection
and wasn't a real queue, so this solution should improve the
overall latency under load.
-rw-r--r-- | src/cowboy_listener.erl | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/src/cowboy_listener.erl b/src/cowboy_listener.erl index 51805b9..b12e059 100644 --- a/src/cowboy_listener.erl +++ b/src/cowboy_listener.erl @@ -27,7 +27,7 @@ -record(state, { req_pools = [] :: pools(), reqs_table :: ets:tid(), - queue = [] :: [{pid(), reference()}], + queue = undefined :: queue(), max_conns = undefined :: non_neg_integer(), proto_opts :: any(), proto_opts_vsn = 1 :: non_neg_integer() @@ -100,8 +100,9 @@ set_protocol_options(ServerPid, ProtoOpts) -> -spec init(list()) -> {ok, #state{}}. init([MaxConns, ProtoOpts]) -> ReqsTable = ets:new(requests_table, [set, private]), + Queue = queue:new(), {ok, #state{reqs_table=ReqsTable, max_conns=MaxConns, - proto_opts=ProtoOpts}}. + proto_opts=ProtoOpts, queue=Queue}}. %% @private -spec handle_call(_, _, State) @@ -115,7 +116,8 @@ handle_call({add_connection, Pool, ConnPid, AccOptsVsn}, From, State=#state{ if AccOptsVsn =/= LisOptsVsn -> {reply, {ugprade, ProtoOpts, LisOptsVsn}, State2}; NbConns > MaxConns -> - {noreply, State2#state{queue=[From|Queue]}}; + Queue2 = queue:in(From, Queue), + {noreply, State2#state{queue=Queue2}}; true -> {reply, ok, State2} end; @@ -193,18 +195,18 @@ move_pid(ConnPid, DestPool, Pools, ReqsTable) -> [{SrcPool, SrcNbConns - 1}, {DestPool, DestNbConns}|Pools2]. %% @private --spec remove_pid(pid(), pools(), ets:tid(), [{pid(), reference()}]) - -> {pools(), [{pid(), reference()}]}. +-spec remove_pid(pid(), pools(), ets:tid(), queue()) -> {pools(), queue()}. remove_pid(Pid, Pools, ReqsTable, Queue) -> {MonitorRef, Pool} = ets:lookup_element(ReqsTable, Pid, 2), erlang:demonitor(MonitorRef, [flush]), {Pool, NbConns} = lists:keyfind(Pool, 1, Pools), Pools2 = [{Pool, NbConns - 1}|lists:keydelete(Pool, 1, Pools)], ets:delete(ReqsTable, Pid), - case Queue of - [] -> + case queue:len(Queue) of + 0 -> {Pools2, Queue}; - [Client|Queue2] -> + _ -> + {{value, Client}, Queue2} = queue:out(Queue), gen_server:reply(Client, ok), {Pools2, Queue2} end. |