Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

56 linhas
1.9 KiB

  1. %%% @doc
  2. %%% This module contains a small parallel dispatch queue that allows
  3. %%% to take a list of jobs and run as many of them in parallel as there
  4. %%% are schedulers ongoing.
  5. %%%
  6. %%% Original design by Max Fedorov in the rebar compiler, then generalised
  7. %%% and extracted here to be reused in other circumstances.
  8. %%% @end
  9. -module(rebar_parallel).
  10. -export([queue/5]).
  11. -include("rebar.hrl").
  12. queue(Tasks, WorkF, WArgs, Handler, HArgs) ->
  13. Parent = self(),
  14. Worker = fun() -> worker(Parent, WorkF, WArgs) end,
  15. Jobs = min(length(Tasks), erlang:system_info(schedulers)),
  16. ?DEBUG("Starting ~B worker(s)", [Jobs]),
  17. Pids = [spawn_monitor(Worker) || _ <- lists:seq(1, Jobs)],
  18. parallel_dispatch(Tasks, Pids, Handler, HArgs).
  19. parallel_dispatch([], [], _, _) ->
  20. [];
  21. parallel_dispatch(Targets, Pids, Handler, Args) ->
  22. receive
  23. {ready, Worker} when is_pid(Worker), Targets =:= [] ->
  24. Worker ! empty,
  25. parallel_dispatch(Targets, Pids, Handler, Args);
  26. {ready, Worker} when is_pid(Worker) ->
  27. [Task|Tasks] = Targets,
  28. Worker ! {task, Task},
  29. parallel_dispatch(Tasks, Pids, Handler, Args);
  30. {'DOWN', Mref, _, Pid, normal} ->
  31. NewPids = lists:delete({Pid, Mref}, Pids),
  32. parallel_dispatch(Targets, NewPids, Handler, Args);
  33. {'DOWN', _Mref, _, _Pid, Info} ->
  34. ?ERROR("Task failed: ~p", [Info]),
  35. ?FAIL;
  36. {result, Result} ->
  37. case Handler(Result, Args) of
  38. ok ->
  39. parallel_dispatch(Targets, Pids, Handler, Args);
  40. {ok, Acc} ->
  41. [Acc | parallel_dispatch(Targets, Pids, Handler, Args)]
  42. end
  43. end.
  44. worker(QueuePid, F, Args) ->
  45. QueuePid ! {ready, self()},
  46. receive
  47. {task, Task} ->
  48. QueuePid ! {result, F(Task, Args)},
  49. worker(QueuePid, F, Args);
  50. empty ->
  51. ok
  52. end.