Главный способ связи с процессом в пространстве Erlang VM - это сообщение, передающееся с erlang:send/2
или erlang:send/3
функциями (псевдоним !
). Но вы можете «взломать» Erlang и использовать несколько способов для общения через процесс.
Вы можете использовать erlang:link/1
для передачи статистики процесса, в основном используемого в случае, если ваш процесс умирает или закончился или что-то не так (исключение или выброс).
Вы можете использовать erlang:monitor/2
, это похоже на erlang:link/1
, за исключением того, что сообщение отправляется непосредственно в почтовый ящик процесса.
Вы также можете взломать Erlang и использовать какой-то внутренний путь (общий ETS
/DETS
/Mnesia
таблицы) или использовать внешние методы (базы данных или другие подобные вещи). Это явно не рекомендуется и «уничтожает» философию Эрланга ... Но вы можете это сделать.
По-видимому, ваша проблема может быть решена с помощью поведения supervisor
.supervisor
поддержка многих strategies контролировать контролируемую процесс:
one_for_one
: Если один дочерний процесс завершается и должен быть перезапущен, только что дочерний процесс влияет. Это стратегия перезапуска по умолчанию.
one_for_all
: Если один дочерний процесс завершается и должен быть перезапущен, все остальные дочерние процессы завершаются, а затем все дочерние процессы перезапускаются.
rest_for_one
: Если один дочерний процесс завершается и должен быть перезапущен, «остальное» дочерних процессов (то есть дочерние процессы после прекращенного дочернего процесса в порядке запуска) завершаются. Затем завершается дочерний процесс и все дочерние процессы после его перезапуска.
simple_one_for_one
: Упрощенный супервизор one_for_one, где все дочерние процессы динамически добавляются экземплярами одного и того же типа процесса, то есть выполняется тот же код.
Вы также можете изменить или создать свою собственную стратегию Прораб с нуля или базы на supervisor_bridge
.
Итак, чтобы подвести итог, вам нужен процесс, который ждет один или несколько завершающих процессов. Это поведение поддерживается с OTP, но вы также можете создать свою собственную модель. Для этого вам нужно предоставить общий статус каждому запущенному процессу, используя кэш или базу данных или когда ваш процесс порожден. Нечто подобное:
Fun = fun
MyFun (ParentProcess, {result, Data})
when is_pid(ParentProcess) ->
ParentProcess ! {self(), Data};
MyFun (ParentProcess, MyData)
when is_pid(ParentProcess) ->
% do something
MyFun(ParentProcess, MyData2) end.
spawn(fun() -> Fun(self(), InitData) end).
EDIT: забыл добавить пример без send
/receive
. Я использую таблицу ETS
для хранения каждого результата из лямбда-функции. Эта таблица ETS
устанавливается, когда мы запускаем этот процесс. Чтобы получить результат, мы можем выбрать данные из этой таблицы. Примечание. Ключом строки является идентификатор процесса процесса.
spawner(Ets, Fun, Args)
when is_integer(Ets),
is_function(Fun) ->
spawn(fun() -> Fun(Ets, Args) end).
Fun = fun
F(Ets, {result, Data}) ->
ets:insert(Ets, {self(), Data});
F(Ets, Data) ->
% do something here
Data2 = Data,
F(Ets, Data2) end.
Для чего это необходимо? почему бы просто не запустить этот «fun()» из основного процесса? –
@ A.Sarid передается многим клиентам параллельно (скажем, 5 процессов, каждый обрабатывает клиенты nbr_clients/5') –
Ну, я не думаю, что вам нужно беспокоиться об использовании блока 'trap_exit' и' receive'. Передача сообщений является одной из главных вещей в Эрланге. Вы не будете «загрязнять» почтовый ящик. –