【问题标题】:Erlang: Trying to generate sets of monitors that only monitor 10 child processesErlang:尝试生成仅监视 10 个子进程的监视器集
【发布时间】:2015-01-13 19:24:24
【问题描述】:

所以我们的想法是,我们需要接收多个子进程来生成/监控,但我们需要启动监控进程,使它们一次只能处理少于 10 个子进程。因此,如果我们接收 35 个子进程,我们需要 4 个监视器,3 个监视 10 个子进程,一个监视 5 个。

问题是我很难弄清楚为什么我为此目的编写的代码会失败。代码如下:

-module(watcher).
-import(sensor, [start/0]).
-export([start/1, stop/0]).

start(NrSlaves) ->
    MasterPids = [],
    MasterPid = spawn(fun() -> master_starter(NrSlaves, MasterPids) end),
    register(master, MasterPid),
    ok.

stop() ->
    master ! die,
    ok.

slave_pid_to_nr(SlavePid, SlavePids) ->
    slave_pid_to_nr(SlavePid, SlavePids, 1).

slave_pid_to_nr(SlavePid, [SlavePid | _Tail], SlaveNr) ->
    SlaveNr;

slave_pid_to_nr(SlavePid, [_Head | Tail], SlaveNr) ->
    slave_pid_to_nr(SlavePid, Tail, SlaveNr + 1).

slave_change_pid(OldSlavePid, NewSlavePid, SlavePids) ->
    lists:map(
      fun(Pid) ->
          if
              Pid == OldSlavePid ->
                  NewSlavePid;
              true ->
                  Pid
          end
      end,
      SlavePids
    ).
%This is the part that errors out
master_starter(NrSlaves, MasterPids) ->
    if (NrSlaves/10) =< 1 ->
        MasterPids = MasterPids ++ [spawn_link(fun() -> master_start(NrSlaves) end)];
    true->
        MasterPids = MasterPids ++ [spawn_link(fun() -> master_start(10) end) || lists:seq(1, (NrSlaves/10))],
        master_starter(NrSlaves-10, MasterPids)
    end,

    receive
        die ->
            io:fwrite("Monitor: received die~n"),
            lists:foreach(fun(MasterPid) -> MasterPid ! die end, MasterPids)
    end.

master_start(NrSlaves) ->
    process_flag(trap_exit, true),
    io:fwrite("monitor: started~n", []),
    SlavePids = [spawn_link(fun() -> slave_start(SlaveNr) end) || SlaveNr <- lists:seq(1, NrSlaves)],
    master_loop(SlavePids).

master_loop(SlavePids) ->
    receive
        die ->
            io:fwrite("Monitor: received die~n"),
            lists:foreach(fun(SlavePid) -> SlavePid ! die end, SlavePids);
        {SlaveNr, Measurement} ->
            io:fwrite("Sensor# ~p measures ~p~n", [SlaveNr, Measurement]),
            master_loop(SlavePids);
        {'EXIT', SlavePid, _Reason} ->
            SlaveNr = slave_pid_to_nr(SlavePid, SlavePids),
            io:fwrite("Monitor: Sensor ~p with PID ~p died because of a crash~n", [SlaveNr, SlavePid]),
            NewSlavePid = spawn_link(fun() -> slave_start(SlaveNr) end),
            NewSlavePids = slave_change_pid(SlavePid, NewSlavePid, SlavePids),
            master_loop(NewSlavePids)
    end.

slave_start(SlaveNr) ->
    % SlavePid = lists:nth(SlaveNr, SlavePids),
    io:fwrite("sensor ~p with PID ~p: started~n", [SlaveNr, self()]),
    %%slave_loop(SlaveNr).
    sensor:start(SlaveNr).

我收到如下错误:“进程中的错误 退出值:{{badmatch,[]},[{watcher,master_starter,2,[{file,"watcher .erl"},{line,39}]}]}"

任何帮助将不胜感激。它非常接近完成,但我只需要了解为什么这不起作用。

【问题讨论】:

    标签: concurrency erlang


    【解决方案1】:

    变量在 erlang 中是不可变的。所以

    MasterPids = MasterPids ++ [spawn_link(fun() -> master_start(NrSlaves) end)];
    

    将失败,因为您尝试修改 MasterPids

    【讨论】:

      【解决方案2】:

      我在您的代码中看到了三个问题。

      变量是不可变的,MasterPids = MasterPids ++ ... 将失败并出现badmatch 错误。尝试分配给NewPidsMasterPids2 等新变量。

      列表理解中缺少生成器。你应该在某处有&lt;-,比如[spawn_link( ... ) || _ &lt;- lists:seq(1, (NrSlaves/10)).

      lists:seq 不接受浮点数。您必须将 NrSlaves/10 向上舍入为整数。您可以使用ceiling function from here(可能会简化一点,因为您不会使用负数)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-02
        • 2013-01-25
        • 2017-07-21
        • 1970-01-01
        • 2010-12-31
        • 2017-10-30
        • 1970-01-01
        相关资源
        最近更新 更多