Понимание возвращаемого значения spawn - PullRequest
4 голосов
/ 21 июня 2011

Я начинаю работать с Erlang и могу немного помочь в понимании различных результатов при применении PID, возвращенного из spawn/3 в метод process_info/1.

Учитывая этот простой код, где *Экспортируется функция 1005 *, которая просто вызывает b/0, которая ожидает сообщения:

-module(tester).
-export([a/0]).

a() ->
    b().
b() ->
    receive {Pid, test} ->
        Pid ! alrighty_then
    end.

... пожалуйста, помогите мне понять причину отличия вывода из оболочки:


Пример 1:

Здесь current_function из Pid показано как tester:b/0:

Pid = spawn(tester, a, []).

process_info( Pid ).

> [{current_function,{tester,b,0}},
    {initial_call,{tester,a,0}},
    ...

Пример 2:

Здесь current_function из process_info/1 отображается как tester:a/0:

process_info( spawn(tester, a, []) ).

> [{current_function,{tester,a,0}},
    {initial_call,{tester,a,0}},
    ...

Пример 3:

Здесь current_function из process_info/1 показано как tester:a/0, но current_function из Pid равно tester:b/0:

process_info( Pid = spawn(tester, a, []) ).

> [{current_function,{tester,a,0}},
    {initial_call,{tester,a,0}},
    ...

process_info( Pid ).

> [{current_function,{tester,b,0}},
    {initial_call,{tester,a,0}},
    ...

Я предполагаю, что при вызове spawn/3 происходит некоторый асинхронный код, но как работает назначение переменных и передача аргументов (особенно в последнем примере), так что Pid получает одно значение,и process_info/1 получает другой?

Есть ли в Erlang что-то особенное, что связывает присвоение переменных в таких случаях, но такая передача не предлагается для передачи аргументов?


EDIT:

Если я использую функцию, подобную этой:

TestFunc = fun( P ) -> P ! {self(), test}, flush() end.

TestFunc( spawn(tester,a,[]) ).

... сообщение возвращается правильно из tester:b/0:

Shell got alrighty_then
ok

Ноесли я использую функцию, подобную этой:

TestFunc2 = fun( P ) -> process_info( P ) end.

TestFunc2( spawn(tester,a,[]) ).

... process_info/1 по-прежнему показывает tester:a/0:

[{current_function,{tester,a,0}},
 {initial_call,{tester,a,0}},
 ...

Не уверен, что делать со всем этим.Возможно, мне просто нужно принять это как уровень моей зарплаты!

Ответы [ 2 ]

9 голосов
/ 21 июня 2011

Если вы посмотрите на документы для spawn , он говорит, что возвращает вновь созданный Pid и помещает новый процесс в очередь системного планировщика. Другими словами, процесс запускается, но вызывающая сторона продолжает выполнение.

Erlang отличается от некоторых других языков тем, что вам не нужно явно отдавать управление, а вы полагаетесь на планировщик процессов, чтобы определить, когда выполнять какой процесс. В тех случаях, когда вы выполняли присваивание Pid, у планировщика было достаточно времени, чтобы переключиться на порожденный процесс, который впоследствии сделал вызов b/0.

6 голосов
/ 21 июня 2011

Это действительно довольно просто.Выполнение порожденного процесса начинается с вызова a (), который в какой-то момент вскоре после этого вызовет b (), а затем просто сидит и ждет, пока не получит конкретное сообщение.В примерах, где вам удается немедленно вызвать process_info для pid, вы ловите его, пока процесс еще выполняет ().В других случаях, когда присутствует некоторая задержка, вы перехватываете ее после вызова b ().Что по этому поводу сбивает с толку?

...