2013-04-30 3 views
0

Я написал следующий код:начальный процесс в процессе Эрл кольца не выйдет из

-module(ring). 

-export([start/3]). 

start(1, 1, Message) -> %special case, no new processes to be launched 
    io:format(" Start/3, branch 1~n~n"), 
    loop(self(), 1, 1), 
    self() ! Message, 
    self() ! {self(), quit}; 
start(1, MsgNum, Message) when MsgNum > 1 -> %first process, register self, launch next, send message, loop 
    io:format(" Start/3 branch 2, ProcNum: ~b, MsgNum: ~b, process: ~p~n~n", [1, MsgNum, self()]), 
    register(process_1, self()), 
    self() ! {self(), Message}, 
    NextPid = spawn(ring, start, [2, MsgNum, Message]), 
    NextPid ! {self(), Message}, 
    loop(NextPid, 1, MsgNum); 
start(MsgNum, MsgNum, _) when MsgNum >= 1 -> %last process, don't start new process, quit master, run loop 
    io:format(" Start/3 branch 3, MsgNum = ProcNum = ~b, process: ~p~n~n", [MsgNum, self()]), 
    process_1 ! {self(), quit}, 
    loop(process_1, MsgNum, MsgNum); 
start(ProcNum, MsgNum, Message) when ProcNum >= 1 -> %everything else, start next process, send it a message, start loop 
    io:format(" Start/3 branch 4, ProcNum: ~b, MsgNum: ~b, process: ~p~n~n", [ProcNum, MsgNum, self()]), 
    NextPid = spawn(ring, start, [ProcNum + 1, MsgNum, Message]), 
    NextPid ! {self(), Message}, 
    loop(NextPid, ProcNum, MsgNum). 

loop(NextPid, ProcNum, MsgNum) -> 
    receive 
     {Sender, quit} -> % send quit to next process in queue, then terminate with 'ok' 
     io:format(" Sender: ~p Quitting process ~p Next: ~p~n~n", [Sender, self(), NextPid]), 
     NextPid ! {self(), quit}, 
     ok; 
    {Sender, Msg} -> % print message and wait for next message 
     io:format(" Message: ~w~n procNum: ~b msgNum: ~b sender: ~p self: ~p next: ~p~n~n", [Msg, ProcNum, MsgNum, Sender, self(), NextPid]), 
     loop(NextPid, ProcNum, MsgNum); 
    _ -> %flush garbage, should never get here... 
     io:format(" Oops. Received someting unexpected") 
    end. 

Я ожидаю, что этот код, чтобы запустить серию процессов, которые должны каждый печать одно сообщение, а затем вежливо бросить курить. Например, если я запустил ring: start (1,3, hola), я ожидаю увидеть три процесса, три сообщения и три выхода. И это почти работает, за исключением того, что первоначальный процесс не прекращается, как видно на этой оболочки сессии:

Eshell V5.10.1 (abort with ^G) 
1> c(ring). 
{ok,ring} 
2> processes(). 
[<0.0.0>,<0.3.0>,<0.6.0>,<0.7.0>,<0.9.0>,<0.10.0>,<0.11.0>, 
<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,<0.16.0>,<0.17.0>, 
<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,<0.22.0>,<0.23.0>, 
<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,<0.28.0>,<0.32.0>] 
3> ring:start(1,3,hola). 
Start/3 branch 2, ProcNum: 1, MsgNum: 3, process: <0.32.0> 

Message: hola 
    procNum: 1 msgNum: 3 sender: <0.32.0> self: <0.32.0> next: <0.41.0> 

Start/3 branch 4, ProcNum: 2, MsgNum: 3, process: <0.41.0> 

Message: hola 
    procNum: 2 msgNum: 3 sender: <0.32.0> self: <0.41.0> next: <0.42.0> 

Start/3 branch 3, MsgNum = ProcNum = 3, process: <0.42.0> 

Message: hola 
    procNum: 3 msgNum: 3 sender: <0.41.0> self: <0.42.0> next: process_1 

Sender: <0.42.0> Quitting process <0.32.0> Next: <0.41.0> 

Sender: <0.32.0> Quitting process <0.41.0> Next: <0.42.0> 

Sender: <0.41.0> Quitting process <0.42.0> Next: process_1 

ok 
4> processes(). 
[<0.0.0>,<0.3.0>,<0.6.0>,<0.7.0>,<0.9.0>,<0.10.0>,<0.11.0>, 
<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,<0.16.0>,<0.17.0>, 
<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,<0.22.0>,<0.23.0>, 
<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,<0.28.0>,<0.32.0>] 

Прошу прощения за длинный код блоков регистрации /, но я думаю, что это делает его очень ясно, что старт/3 инициирует запуск трех процессов (< 0.32.0>, < 0.41.0> и < 0.42.0>), и каждый печатает одно сообщение и каждый получает свое сообщение о выходе. Однако, когда все сделано, начальный процесс (< 0.32.0>) все еще работает. Мое понимание заключается в том, что процесс должен завершиться, если нет никакого кода для запуска - есть ли что-то особенное в первом процессе, который предотвращает его прекращение?

Заранее спасибо.

ответ

4

Ваша функция start/3 не запускает процесс, который вы называете «начальным». Вместо этого функция запускается в процессе, который уже существует. Это процесс оболочки erlang, и вы работаете с ним. Он имеет pid < 0.32.0>. Посмотрите внимательно на выходе первого вызова функциональных процессов():

2> processes(). 
[<0.0.0>,<0.3.0>,<0.6.0>,<0.7.0>,<0.9.0>,<0.10.0>,<0.11.0>, 
<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,<0.16.0>,<0.17.0>, 
<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,<0.22.0>,<0.23.0>, 
<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,<0.28.0>,<0.32.0>] 

Последний PID в списке < 0.32.0>. Поэтому, когда вы вызываете start/3, он запускается внутри этого процесса, и когда он выходит из цикла, процесс < 0.32.0> не будет завершен - он вернется только к оболочке erlang и подождет следующую команду.

+0

Конечно :-) Спасибо за четкое и краткое объяснение. – Ampers4nd

Смежные вопросы