Erlang Language
Processi
Ricerca…
Creazione di processi
Creiamo un nuovo processo concorrente chiamando la funzione spawn
. La funzione di spawn
avrà come parametro una funzione Fun
che il processo valuterà. Il valore di ritorno della funzione spawn
è l'identificatore del processo creato (pid).
1> Fun = fun() -> 2+2 end.
#Fun<erl_eval.20.52032458>
2> Pid = spawn(Fun).
<0.60.0>
Puoi anche usare spawn/3
per avviare un processo che eseguirà una funzione specifica da un modulo: spawn(Module, Function, Args)
.
Oppure usa spawn/2
o spawn/4
modo simile per avviare un processo in un nodo diverso: spawn(Node, Fun)
o spawn(Node, Module, Function, Args)
.
Messaggio in corso
Due processi di erlang possono comunicare tra loro, noto anche come passaggio di messaggi .
Questa procedura è asincrona nella forma in cui il processo di invio non si interrompe dopo l'invio del messaggio.
Invio di messaggi
Questo può essere ottenuto con il costrutto Pid ! Message
, dove Pid
è un identificatore di processo valido (pid) e Message
è un valore di qualsiasi tipo di dati.
Ogni processo ha una "casella di posta" che contiene i messaggi ricevuti nell'ordine ricevuto. Questa "casella di posta" può essere svuotata con la funzione flush/0
.
Se un messaggio viene inviato a un processo non esistente, il messaggio verrà eliminato senza errori!
Un esempio potrebbe essere simile al seguente, dove self/0
restituisce il pid del processo corrente e pid/3
crea un 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
È anche possibile inviare un messaggio a più processi contemporaneamente, con Pid3!Pid2!Pid1!Msg
.
Ricevere messaggi
I messaggi ricevuti possono essere elaborati con il costrutto di receive
.
receive
Pattern1 -> exp11, .., exp1n1;
Pattern2 when Guard -> exp21, .., exp2n2;
...
Other -> exp31, .., exp3n3;
...
after Timeout -> exp41, .., exp4n4
end
Il Pattern
verrà confrontato con i messaggi nella "mailbox" a partire dal primo e dal messaggio meno recente.
Se un modello corrisponde, il messaggio corrispondente viene rimosso dalla "cassetta postale" e il corpo della clausola viene valutato.
È anche possibile definire i timeout con il after
costrutto.
Un Timeout
è il tempo di attesa in millisecondi o l' infinity
dell'atomo.
Il valore di ritorno di receive
è l'ultimo corpo della clausola valutata.
Esempio (contatore)
Un contatore (molto) semplice con il passaggio del messaggio potrebbe essere simile a quanto segue.
-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.
Interazione con il contatore.
1> C0 = counter0:start().
<0.39.0>
2> C0!increment.
increment
3> C0!increment.
increment
Registra i processi
È possibile registrare un processo (pid) in un alias globale.
Questo può essere ottenuto con la funzione build in register(Alias, Pid)
, dove Alias
è l'atomo per accedere al processo e Pid
è l'id del processo.
L'alias sarà disponibile a livello globale!
È molto facile creare uno stato condiviso, che di solito non è preferibile. ( Vedi anche qui )
È possibile whereis(Alias)
registrazione di un processo con un whereis(Alias)
unregister(Pid)
e ricevere il pid da un alias con whereis(Alias)
.
Utilizzare registered()
per un elenco di tutti gli alias registrati.
L'esempio registra Atom foo nel pid del processo corrente e invia un messaggio utilizzando l'Atom registrato.
1> register(foo, self()).
true
2> foo ! 'hello world'.
'hello world'