Erlang Language
Процессы
Поиск…
Создание процессов
Мы создаем новый параллельный процесс, вызывая функцию spawn . Функция spawn получит в качестве параметра функцию Fun которую процесс будет оценивать. Возвращаемое значение функции spawn - это созданный идентификатор процесса (pid).
1> Fun = fun() -> 2+2 end.
#Fun<erl_eval.20.52032458>
2> Pid = spawn(Fun).
<0.60.0>
Вы также можете использовать spawn/3 для запуска процесса, который будет выполнять определенную функцию из модуля: spawn(Module, Function, Args) .
Или используйте spawn/2 или spawn/4 аналогично, чтобы запустить процесс в другом узле: spawn(Node, Fun) или spawn(Node, Module, Function, Args) .
Передача сообщений
Два процесса erlang могут взаимодействовать друг с другом, что также известно как передача сообщений .
Эта процедура является асинхронной в том виде, в котором процесс отправки не будет остановлен после отправки сообщения.
Отправка сообщений
Это может быть достигнуто с помощью конструкции Pid ! Message , где Pid является допустимым идентификатором процесса (pid), а Message - значением любого типа данных.
Каждый процесс имеет «почтовый ящик», который содержит полученные сообщения в полученном порядке. Этот «почтовый ящик» может быть опустошен с помощью встроенной функции flush/0 .
Если сообщение отправляется в не существующий процесс, сообщение будет отброшено без каких-либо ошибок!
Пример может выглядеть следующим образом: self/0 возвращает pid текущего процесса, а pid/3 создает pid.
1> Pidsh = self().
<0.32.0>
2> Pidsh ! hello.
hello
3> flush().
Shell got hello
ok
4> <0.32.0> ! hello.
* 1: syntax error before: ’<’
5> Pidsh2 = pid(0,32,0).
<0.32.0>
6> Pidsh2 ! hello2.
hello2
7> flush().
Shell got hello2
ok
Также можно отправить сообщение нескольким процессам сразу, с Pid3!Pid2!Pid1!Msg .
Получение сообщений
Полученные сообщения могут обрабатываться с помощью конструкции receive .
receive
Pattern1 -> exp11, .., exp1n1;
Pattern2 when Guard -> exp21, .., exp2n2;
...
Other -> exp31, .., exp3n3;
...
after Timeout -> exp41, .., exp4n4
end
Pattern будет сравниваться с сообщениями в «почтовом ящике», начиная с первого и самого старого сообщений.
Если шаблон совпадает, совпадающее сообщение удаляется из «почтового ящика» и вычисляется тело предложения.
Также можно определить тайм-ауты с after конструкцией.
Timeout - это либо время ожидания в миллисекундах, либо infinity атома.
Возвращаемое значение receive - это последний обработанный объект предложения.
Пример (счетчик)
A (очень) простой счетчик с передачей сообщений может выглядеть следующим образом.
-module(counter0).
-export([start/0,loop/1]).
% Creating the counter process.
start() ->
spawn(counter0, loop, [0]).
% The counter loop.
loop(Val) ->
receive
increment ->
loop(Val + 1)
end.
Взаимодействие с прилавком.
1> C0 = counter0:start().
<0.39.0>
2> C0!increment.
increment
3> C0!increment.
increment
Регистрация процессов
Можно зарегистрировать процесс (pid) для глобального псевдонима.
Это может быть достигнуто с помощью функции создания в register(Alias, Pid) , где Alias является атомом для доступа к процессу, а Pid - идентификатором процесса.
Псевдоним будет доступен по всему миру!
Очень просто создать общее состояние, которое обычно не является предпочтительным. ( См. Также здесь )
Можно отменить регистрацию процесса с unregister(Pid) и получить pid из псевдонима whereis(Alias) .
Используйте registered() список всех зарегистрированных псевдонимов.
Пример регистрирует Atom foo для pid текущего процесса и отправляет сообщение с использованием зарегистрированного Atom.
1> register(foo, self()).
true
2> foo ! 'hello world'.
'hello world'