|
44 | 44 | size = 5 :: non_neg_integer(),
|
45 | 45 | overflow = 0 :: non_neg_integer(),
|
46 | 46 | max_overflow = 10 :: non_neg_integer(),
|
47 |
| - strategy = lifo :: lifo | fifo |
| 47 | + strategy = lifo :: lifo | fifo, |
| 48 | + lazy = false :: boolean() |
48 | 49 | }).
|
49 | 50 |
|
50 | 51 | -spec checkout(Pool :: pool()) -> pid().
|
@@ -162,8 +163,13 @@ init([{strategy, lifo} | Rest], WorkerArgs, State) ->
|
162 | 163 | init(Rest, WorkerArgs, State#state{strategy = lifo});
|
163 | 164 | init([{strategy, fifo} | Rest], WorkerArgs, State) ->
|
164 | 165 | init(Rest, WorkerArgs, State#state{strategy = fifo});
|
| 166 | +init([{lazy, true} | Rest], WorkerArgs, State) -> |
| 167 | + init(Rest, WorkerArgs, State#state{lazy = true}); |
165 | 168 | init([_ | Rest], WorkerArgs, State) ->
|
166 | 169 | init(Rest, WorkerArgs, State);
|
| 170 | +init([], _WorkerArgs, #state{lazy = true, size = Size} = State) -> |
| 171 | + Workers = prepopulate_empty(Size), |
| 172 | + {ok, State#state{workers = Workers}}; |
167 | 173 | init([], _WorkerArgs, #state{size = Size, supervisor = Sup} = State) ->
|
168 | 174 | Workers = prepopulate(Size, Sup),
|
169 | 175 | {ok, State#state{workers = Workers}}.
|
@@ -208,6 +214,10 @@ handle_call({checkout, CRef, Block}, {FromPid, _} = From, State) ->
|
208 | 214 | max_overflow = MaxOverflow,
|
209 | 215 | strategy = Strategy} = State,
|
210 | 216 | case get_worker_with_strategy(Workers, Strategy) of
|
| 217 | + {{value, undefined}, Left} -> |
| 218 | + {Pid, MRef} = new_worker(Sup, FromPid), |
| 219 | + true = ets:insert(Monitors, {Pid, CRef, MRef}), |
| 220 | + {reply, Pid, State#state{workers = Left}}; |
211 | 221 | {{value, Pid}, Left} ->
|
212 | 222 | MRef = erlang:monitor(process, FromPid),
|
213 | 223 | true = ets:insert(Monitors, {Pid, CRef, MRef}),
|
@@ -268,6 +278,9 @@ handle_info({'EXIT', Pid, _Reason}, State) ->
|
268 | 278 | {noreply, NewState};
|
269 | 279 | [] ->
|
270 | 280 | case queue:member(Pid, State#state.workers) of
|
| 281 | + true when State#state.lazy =:= true -> |
| 282 | + W = filter_worker_by_pid(Pid, State#state.workers), |
| 283 | + {noreply, State#state{workers = queue:in(undefined, W)}}; |
271 | 284 | true ->
|
272 | 285 | W = filter_worker_by_pid(Pid, State#state.workers),
|
273 | 286 | {noreply, State#state{workers = queue:in(new_worker(Sup), W)}};
|
@@ -328,6 +341,11 @@ prepopulate(0, _Sup, Workers) ->
|
328 | 341 | prepopulate(N, Sup, Workers) ->
|
329 | 342 | prepopulate(N-1, Sup, queue:in(new_worker(Sup), Workers)).
|
330 | 343 |
|
| 344 | +prepopulate_empty(N) when N < 1 -> |
| 345 | + queue:new(); |
| 346 | +prepopulate_empty(N) -> |
| 347 | + queue:from_list([undefined || _ <- lists:seq(1, N)]). |
| 348 | + |
331 | 349 | handle_checkin(Pid, State) ->
|
332 | 350 | #state{supervisor = Sup,
|
333 | 351 | waiting = Waiting,
|
@@ -358,6 +376,10 @@ handle_worker_exit(Pid, State) ->
|
358 | 376 | State#state{waiting = LeftWaiting};
|
359 | 377 | {empty, Empty} when Overflow > 0 ->
|
360 | 378 | State#state{overflow = Overflow - 1, waiting = Empty};
|
| 379 | + {empty, Empty} when State#state.lazy =:= true -> |
| 380 | + W = filter_worker_by_pid(Pid, State#state.workers), |
| 381 | + Workers = queue:in(undefined, W), |
| 382 | + State#state{workers = Workers, waiting = Empty}; |
361 | 383 | {empty, Empty} ->
|
362 | 384 | W = filter_worker_by_pid(Pid, State#state.workers),
|
363 | 385 | Workers = queue:in(new_worker(Sup), W),
|
|
0 commit comments