Browse Source

Merge pull request #1 from uwiger/master

sync with uwiger/gproc
abogosyan 6 years ago
parent
commit
292bb206d6
3 changed files with 46 additions and 10 deletions
  1. 2 0
      src/gproc.erl
  2. 15 10
      src/gproc_pool.erl
  3. 29 0
      test/gproc_tests.erl

+ 2 - 0
src/gproc.erl

@@ -2489,6 +2489,8 @@ handle_reg_call(Key, Pid, Val, Attrs, Op, S) ->
                     %% actually pretty bad, if it ever happens
                     {reply, badarg, S}
             end;
+        already_registered ->
+            {reply, badarg, S};
         false ->
             {reply, badarg, S}
     end.

+ 15 - 10
src/gproc_pool.erl

@@ -827,24 +827,29 @@ remove_worker_(Pool, Name) ->
 
 do_remove_worker_(Pool, Name) ->
     K = ?POOL(Pool),
+    AutoSize = gproc:get_attribute(K, shared, auto_size),
     Ws0 = get_workers_(K),
-    Ws1 = del_slot(Name, Ws0),
+    Ws1 = del_slot(Name, Ws0, AutoSize),
     gproc:unreg_shared(?POOL_WRK(Pool, Name)),
-    case (NewLen = length(Ws1)) - length(Ws0) of
-        0 -> ok;
-        Diff when Diff < 0 ->
-            {_, Type} = gproc:get_value(K, shared),
-            gproc:set_value_shared(K, {NewLen, Type})
+    case AutoSize of
+        false -> ok;
+        true ->
+            case (NewLen = length(Ws1)) - length(Ws0) of
+                0 -> ok;
+                Diff when Diff < 0 ->
+                    {_, Type} = gproc:get_value(K, shared),
+                    gproc:set_value_shared(K, {NewLen, Type})
+            end
     end,
     gproc:set_attributes_shared(K, [{workers, Ws1}]),
     ok.
 
-del_slot(Name, [{Name,_}]) ->
+del_slot(Name, [{Name,_}], true) ->
     [];
-del_slot(Name, [{Name, Pos}|T]) ->
+del_slot(Name, [{Name, Pos}|T], _AutoSize) ->
     [Pos|T];
-del_slot(Name, [H|T]) ->
-    [H|del_slot(Name, T)].
+del_slot(Name, [H|T], AutoSize) ->
+    [H|del_slot(Name, T, AutoSize)].
 
 find_slot(Name, _, [], Sz, _, Auto) ->
     case {Sz, Auto} of

+ 29 - 0
test/gproc_tests.erl

@@ -162,6 +162,10 @@ reg_test_() ->
       , ?_test(t_is_clean())
       , {spawn, ?_test(?debugVal(t_simple_pool()))}
       , ?_test(t_is_clean())
+      , {spawn, ?_test(?debugVal(t_pool_add_worker_size_1_no_auto_size()))}
+      , ?_test(t_is_clean())
+      , {spawn, ?_test(?debugVal(t_pool_add_worker_size_2_no_auto_size()))}
+      , ?_test(t_is_clean())
      ]}.
 
 t_simple_reg() ->
@@ -1003,6 +1007,31 @@ t_simple_pool()->
     %% should be able to delete the pool now
     ?assertEqual( gproc_pool:delete(p1), ok).
 
+%% verifying #167 - Removing a worker from a pool does not make room
+%% for a new worker (size was erroneously adjusted down, though auto_size = false)
+t_pool_add_worker_size_1_no_auto_size() ->
+    ok = gproc_pool:new(p2, direct, [{size, 1}, {auto_size, false}]),
+    [] = gproc_pool:defined_workers(p2),
+    Pos1 = gproc_pool:add_worker(p2, worker1),
+    [{worker1, Pos1, 0}] = gproc_pool:defined_workers(p2),
+    io:fwrite("G = ~p~n", [ets:tab2list(gproc)]),
+    true = gproc_pool:remove_worker(p2, worker1),
+    [] = gproc_pool:defined_workers(p2), %% the pool seems to be empty
+    Pos2 = gproc_pool:add_worker(p2, worker2), %% throws error:pool_full
+    true = is_integer(Pos2),
+    true = gproc_pool:force_delete(p2).
+
+t_pool_add_worker_size_2_no_auto_size() ->
+    gproc_pool:new(p3, direct, [{size, 2}, {auto_size, false}]),
+    gproc_pool:add_worker(p3, worker1),
+    gproc_pool:add_worker(p3, worker2),
+    gproc_pool:remove_worker(p3, worker2),
+    gproc_pool:add_worker(p3, worker3),
+    gproc_pool:force_delete(p3).
+
+
+
+
 get_msg() ->
     receive M ->
 	    M