Skip to content

Commit

Permalink
Merge pull request devinus#60 from JYZR/fifo-support
Browse files Browse the repository at this point in the history
Adds support for FIFO strategy
  • Loading branch information
Devin Torres committed Dec 3, 2014
2 parents 7632965 + 31170d0 commit 52d87c2
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -155,6 +155,8 @@ code_change(_OldVsn, State, _Extra) ->
- `worker_module`: the module that represents the workers
- `size`: maximum pool size
- `max_overflow`: maximum number of workers created if pool is empty
- `strategy`: `lifo` or `fifo`, determines whether checked in workers should be
placed first or last in the line of available workers. Default is `lifo`.

## Authors

Expand Down
15 changes: 12 additions & 3 deletions src/poolboy.erl
Expand Up @@ -34,7 +34,8 @@
monitors :: ets:tid(),
size = 5 :: non_neg_integer(),
overflow = 0 :: non_neg_integer(),
max_overflow = 10 :: non_neg_integer()
max_overflow = 10 :: non_neg_integer(),
strategy = lifo :: lifo | fifo
}).

-spec checkout(Pool :: pool()) -> pid().
Expand Down Expand Up @@ -132,6 +133,10 @@ init([{size, Size} | Rest], WorkerArgs, State) when is_integer(Size) ->
init(Rest, WorkerArgs, State#state{size = Size});
init([{max_overflow, MaxOverflow} | Rest], WorkerArgs, State) when is_integer(MaxOverflow) ->
init(Rest, WorkerArgs, State#state{max_overflow = MaxOverflow});
init([{strategy, lifo} | Rest], WorkerArgs, State) ->
init(Rest, WorkerArgs, State#state{strategy = lifo});
init([{strategy, fifo} | Rest], WorkerArgs, State) ->
init(Rest, WorkerArgs, State#state{strategy = fifo});
init([_ | Rest], WorkerArgs, State) ->
init(Rest, WorkerArgs, State);
init([], _WorkerArgs, #state{size = Size, supervisor = Sup} = State) ->
Expand Down Expand Up @@ -279,7 +284,8 @@ handle_checkin(Pid, State) ->
#state{supervisor = Sup,
waiting = Waiting,
monitors = Monitors,
overflow = Overflow} = State,
overflow = Overflow,
strategy = Strategy} = State,
case queue:out(Waiting) of
{{value, {From, Ref}}, Left} ->
true = ets:insert(Monitors, {Pid, Ref}),
Expand All @@ -289,7 +295,10 @@ handle_checkin(Pid, State) ->
ok = dismiss_worker(Sup, Pid),
State#state{waiting = Empty, overflow = Overflow - 1};
{empty, Empty} ->
Workers = [Pid | State#state.workers],
Workers = case Strategy of
lifo -> [Pid | State#state.workers];
fifo -> State#state.workers ++ [Pid]
end,
State#state{workers = Workers, waiting = Empty, overflow = 0}
end.

Expand Down
39 changes: 39 additions & 0 deletions test/poolboy_tests.erl
Expand Up @@ -56,6 +56,15 @@ pool_test_() ->
},
{<<"Pool demonitors when a checkout is cancelled">>,
fun demonitors_when_checkout_cancelled/0
},
{<<"Check that LIFO is the default strategy">>,
fun default_strategy_lifo/0
},
{<<"Check LIFO strategy">>,
fun lifo_strategy/0
},
{<<"Check FIFO strategy">>,
fun fifo_strategy/0
}
]
}.
Expand Down Expand Up @@ -432,6 +441,30 @@ demonitors_when_checkout_cancelled() ->
Pid ! ok,
ok = pool_call(Pool, stop).

default_strategy_lifo() ->
%% Default strategy is LIFO
{ok, Pid} = new_pool(2, 0),
Worker1 = poolboy:checkout(Pid),
ok = poolboy:checkin(Pid, Worker1),
Worker1 = poolboy:checkout(Pid),
poolboy:stop(Pid).

lifo_strategy() ->
{ok, Pid} = new_pool(2, 0, lifo),
Worker1 = poolboy:checkout(Pid),
ok = poolboy:checkin(Pid, Worker1),
Worker1 = poolboy:checkout(Pid),
poolboy:stop(Pid).

fifo_strategy() ->
{ok, Pid} = new_pool(2, 0, fifo),
Worker1 = poolboy:checkout(Pid),
ok = poolboy:checkin(Pid, Worker1),
Worker2 = poolboy:checkout(Pid),
?assert(Worker1 =/= Worker2),
Worker1 = poolboy:checkout(Pid),
poolboy:stop(Pid).

get_monitors(Pid) ->
[{monitors, Monitors}] = erlang:process_info(Pid, [monitors]),
Monitors.
Expand All @@ -441,5 +474,11 @@ new_pool(Size, MaxOverflow) ->
{worker_module, poolboy_test_worker},
{size, Size}, {max_overflow, MaxOverflow}]).

new_pool(Size, MaxOverflow, Strategy) ->
poolboy:start_link([{name, {local, poolboy_test}},
{worker_module, poolboy_test_worker},
{size, Size}, {max_overflow, MaxOverflow},
{strategy, Strategy}]).

pool_call(ServerRef, Request) ->
gen_server:call(ServerRef, Request).

0 comments on commit 52d87c2

Please sign in to comment.