Erlang Language
Procesy
Szukaj…
Tworzenie procesów
Tworzymy nowy równoległy proces, wywołując funkcję spawn
. Funkcja spawn
otrzyma jako parametr funkcję Fun
którą proces oceni. Zwracana wartość funkcji spawn
to utworzony identyfikator procesu (pid).
1> Fun = fun() -> 2+2 end.
#Fun<erl_eval.20.52032458>
2> Pid = spawn(Fun).
<0.60.0>
Możesz także użyć spawn/3
aby uruchomić proces, który wykona określoną funkcję z modułu: spawn(Module, Function, Args)
.
Lub użyj spawn/2
lub spawn/4
podobnie, aby rozpocząć proces w innym węźle: spawn(Node, Fun)
lub spawn(Node, Module, Function, Args)
.
Przekazywanie wiadomości
Dwa procesy erlang mogą się ze sobą komunikować, co jest również znane jako przekazywanie wiadomości .
Ta procedura jest asynchroniczna , ponieważ proces wysyłania nie zostanie zatrzymany po wysłaniu wiadomości.
Wysyłanie wiadomości
Można to osiągnąć za pomocą konstruktu Pid ! Message
, w którym Pid
jest prawidłowym identyfikatorem procesu (pid), a Message
jest wartością dowolnego typu danych.
Każdy proces ma „skrzynkę pocztową”, która zawiera odebrane wiadomości w otrzymanej kolejności. Tę „skrzynkę pocztową” można opróżnić za pomocą flush/0
funkcji flush/0
.
Jeśli wiadomość zostanie wysłana do nieistniejącego procesu, wiadomość zostanie odrzucona bez żadnego błędu!
Przykład może wyglądać następująco: self/0
zwraca pid bieżącego procesu, a pid/3
tworzy 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
Możliwe jest również wysłanie wiadomości do wielu procesów jednocześnie, za pomocą Pid3!Pid2!Pid1!Msg
.
Odbieranie wiadomości
Otrzymane wiadomości mogą być przetwarzane za pomocą konstrukcji receive
.
receive
Pattern1 -> exp11, .., exp1n1;
Pattern2 when Guard -> exp21, .., exp2n2;
...
Other -> exp31, .., exp3n3;
...
after Timeout -> exp41, .., exp4n4
end
Pattern
zostanie porównany z wiadomościami w „skrzynce pocztowej”, zaczynając od pierwszej i najstarszej wiadomości.
Jeśli wzorzec jest zgodny, dopasowana wiadomość jest usuwana z „skrzynki pocztowej” i analizowana jest treść klauzuli.
Możliwe jest również zdefiniowanie limitów czasu za pomocą konstrukcji after
.
Timeout
to czas oczekiwania w milisekundach lub infinity
atomu.
Zwracana wartość parametru receive
jest ostatnią ocenioną treścią klauzuli.
Przykład (licznik)
(Bardzo) prosty licznik z przekazywaniem wiadomości może wyglądać następująco.
-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.
Interakcja z kontuarem.
1> C0 = counter0:start().
<0.39.0>
2> C0!increment.
increment
3> C0!increment.
increment
Zarejestruj procesy
Możliwe jest zarejestrowanie procesu (pid) w globalnym aliasie.
Można to osiągnąć za pomocą funkcji wbudowanego register(Alias, Pid)
, w której Alias
jest atomem umożliwiającym dostęp do procesu, a Pid
jest identyfikatorem procesu.
Alias będzie dostępny na całym świecie!
Bardzo łatwo jest utworzyć stan współdzielony, co zwykle nie jest preferowane. ( Zobacz także tutaj )
Możliwe jest wyrejestrowanie procesu z unregister(Pid)
i otrzymanie pid z aliasu z whereis(Alias)
.
Użyj registered()
aby wyświetlić listę wszystkich zarejestrowanych aliasów.
Przykład rejestruje atom Foo na pid bieżącego procesu i wysyła komunikat za pomocą zarejestrowanego atomu.
1> register(foo, self()).
true
2> foo ! 'hello world'.
'hello world'