1 / 55

Erlang Programming

Erlang Programming. Session 4. Concurrent Programming Processes. Messages. Process pattern. Process aliases. Timeouts. Example: Client-Server model. Processes. Concurrent activities are modeled using light-weight processes. Many processes may be running simultaneously.

gitano
Download Presentation

Erlang Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Erlang Programming

  2. Session 4 • Concurrent Programming • Processes. • Messages. • Process pattern. • Process aliases. • Timeouts. • Example: Client-Server model

  3. Processes • Concurrent activities are modeled using light-weight processes. • Many processes may be running simultaneously. • The identity of the newly created process is returned from the BIF spawn/3: • Code run by PidA: PidB = spawn(Mod, Func, Args) PidA PidA PidB

  4. activity(Joe,75,1024) Erlang Example Creating a new process using spawn -module(ex3). -export([activity/3]). activity(Name,Pos,Size) -> ………… Pid = spawn(ex3,activity,[Joe,75,1024])

  5. Processes spawn(Module, Function, Args). • Creates a new process, i.e. another thread of execution, starting in the function call given by the arguments. • Example: spawn(m, f, [1,2,3]) creates a process starting in m:f(1,2,3).

  6. Processes • The function used in spawn/3 must be exported. • A process will terminate when there is no more code to execute.

  7. Processes • Messages are sent using “!” (Sometimes called bang). Pid ! Msg • Msg is any legal Erlang term • Pid is of type process identifier (most probably returned by spawn)

  8. Processes • Processes communicates by sending and receiving messages hello PidA PidB PidB ! hello receive hello -> ... end

  9. Processes • The BIF self/0 returns the process identifier of the process calling it • Try it in the shell.

  10. Example: Area server -module(area_server0). -export([loop/0]). loop() -> receive {rectangle, Width, Ht} -> io:format("Area of rectangle is ~p~n", [Width * Ht]), loop(); {circle, R} -> io:format("Area of circle is ~p~n" , [3.14159 * R * R]), loop(); Other -> io:format("I don't know what the area of a ~p is ~n" ,[Other]), loop() end.

  11. Example: Area server 1> Pid = spawn(fun area_server0:loop/0). <0.36.0> 2> Pid ! {rectangle, 6, 10}. Area of rectangle is 60 {rectangle,6,10} 3> Pid ! {circle, 23}. Area of circle is 1661.90 {circle,23} 4> Pid ! {triangle,2,4,5}. I don't know what the area of a {triangle,2,4,5} is {triangle,2,4,5}

  12. Transparent Distribution B ! Msg C ! Msg Erlang Run-Time System Erlang Run-Time System network

  13. Process Pattern start() -> spawn(mymod, init, [...]). init() -> <initializations>, loop(...). loop(...) receive stop -> true; %%The process stops here Pattern1 -> <actions>, loop(...); ... PatternN -> <actions>, loop(...) end.

  14. Process example (echo process) A process that receives a message and returns it back to the sender. -module (echo). -export ([start/0, init/0]). start() -> spawn(echo, init, []). init() -> loop(). loop() -> receive stop -> true; {Pid, Msg} -> Pid ! {self(), Msg}, loop() end.

  15. Process example (Testing echo) -module(test_echo). -export([start/1, init/1]). start(N)-> spawn(test_echo, init, [N]). init(N)-> Epid = echo:start(), loop(N, Epid). loop(0, Epid) -> Epid ! stop, io:format("Echo passed this test ~n", []); loop(N, Epid) -> Epid ! {self(), N}, io:format("Sending message, N= ~p~n", [N]), receive stop -> true; {Epid, N} -> loop(N-1, Epid) end.

  16. Process example (echo process) -module (echo). -export ([start/0, init/0]). start() -> spawn(echo, init, []). init() -> loop(). loop()-> receive stop -> io:format("I got message ~p from process ~p~n", [stop, unknown]), true; {Pid, Msg} -> io:format("I got message ~p from process ~p~n", [Msg, Pid]), Pid ! {self(), Msg}, loop() end

  17. Process aliases • To use a name instead of process ID, use the BIF register/2 register(Alias, Pid) • Any process can send a message using the alias. register(iti, Pid), … … iti ! hello, • Sending a message to a non-existant alias, fails.

  18. Timeouts • To be able to program a process that does not wait forever for a message to arrive. receive hello -> io:format(“hi”, []) after 1000 -> %1000 millisec true end.

  19. Timeouts • test_echo with timeouts (in case the echo process dies). loop(N, Epid) -> Epid ! {self(), N}, receive stop -> true; {Epid, N} -> loop(N-1, Epid) after 1000 -> io:format(“Echo timed out”) end.

  20. Example: Client-Server model server.erl PidA • Message protocol: {request, ClientPid, alloc} {reply, Resource} {request, ClientPid, {free, Resource}}  {reply, ok} server PidB PidC hw.erl

  21. Client-Server (cont.) • Server Code -module(server). -export([start/0]). -export([alloc/0, free/1]). -export([init/0]). start() -> spawn(server, init, []). init() -> register(server, self()), Resources = hw:get_resources(), loop(Resources).

  22. Client-Server (cont.) loop(ResDB) -> receive {request, From, alloc} -> {Resources, NewResDB} = hw:alloc(ResDB}, From ! {reply, Resource}, loop(NewResDB}; {requet, From, {free, Resource}}-> From ! {reply, ok}, loop(hw:free(Resource, ResDB)); _Other loop(ResDB) end.

  23. Client-Server (cont.) • Client functions: alloc() -> call(alloc). free(Resource) call({free, Resource}). call(Request) -> server ! {request, self(), Request}, receive {reply, Reply} -> Reply end.

  24. Lesson 4 • Links. • Exit signals. • Trapping exit signals. • Robust systems. • Monitors.

  25. Links • Processes can be linked together using the BIF link(Pid). or spawn_link(Module, Function, Args). Links are removed using: unlink(Pid). PidB PidA

  26. PidB PidA Exit Signals • When a process terminates, exit signals are sent over all links connected to the terminating process EXIT

  27. Exit Signals • A process can terminate: • normally: (when it has no more code to execute). • abnormally: due to run-time error. • abnormally: due to execution of BIF causing termination exit(Reason). • Note: a signal is not a message.

  28. Exit signals • When a process terminates normally (no more code to execute), the emitted exit-signals are ignored by the linked processes. • When the process terminates abnormally, linked process will notice the emitted exit signals… … and terminate themselves 

  29. Exit Signals When a process terminates, an exit signal is sent to all linked processes … and the termination is propagated

  30. PidB PidA Exit Signals • The BIF exit/2 emits an exit-signal to a process even if there is no link between them. exit(DestPid, Reason). • PidA doesn’t terminate, it just terminates PidB EXIT

  31. Trapping exit signals • To protect itself from exit signals, a process uses the BIF: process_flag(trap_exit, true). • Then, incoming exit signals will be transformed to a message and put in the message que in the format: {‘EXIT’, Pid, Reasons}

  32. Trapping exit signals • Trapping exit causes any exit signal to be transformed into a message even signals occuring due to normal termination of linked processes. • When a process PidA is linked to PidB, PidB is trapping exit and PidA terminates normally (no more code to execute), PidB receives the following message: {‘EXIT’, Pid, Reasons} • Remember what happens in the above case when PidB is not trapping exit? • PidB just receives the exit signal but ignores it.

  33. Trapping exit signals • Processes that traps exit can also be killed by sending them an exit signal with reason kill • The process terminates with the reason killed

  34. Summary of trapping exits

  35. Summary of trapping exits

  36. Summary of trapping exits

  37. Summary of trapping exits

  38. Summary of trapping exits

  39. Summary of trapping exits

  40. Summary of trapping exits

  41. Client-Server (robust) • Server Code -module(server). -export([start/0]). -export([alloc/0, free/1]). -export([init/0]). start() -> spawn(server, init, []). init() -> process_flag(trap_exit, true), register(server, self()), Resources = hw:get_resources(), loop(Resources).

  42. Client-Server (cont.) loop(ResDB) -> receive {request, From, alloc} -> {Resources, NewResDB} = hw:alloc(ResDB}, link(From), From ! {reply, Resource}, loop(NewResDB}; {requet, From, {free, Resource}}-> unlink(From), From ! {reply, ok}, loop(hw:free(Resource, ResDB)); {‘EXIT’, From, _Reason}-> <do something> loop(NewResDB); _Other -> loop(ResDB) end.

  43. Monitors • The BIF erlang:monitor/2 offers a way to monitor another process. • The monitor is not bi-directional like links. MRef = erlang:monitor(process, Process). Process = pid() | atom() documentation style • If the process terminates the calling process will receive a {‘DOWN’, MRef, process, Object, Reason}

  44. Exercises • Write a process that upon receiving a certain message terminates normally and when receiving another message terminates ubnormaly. loop() -> receive stop -> io:format("Process stopped~n"); error -> io:format("Process will terminate ubnormally~n"), abc = abcd; Msg -> io:format("Message ~p received ~n", [Msg]), loop() end.

  45. Exercises • Write a function that starts another process • pmon:start(SupervisedPID). • The process shall use a link to monitor the supervised process. • The monitoring process shall print a message if the supervised process terminates abnormally. • The monitoring process should terminate whenever the supervised process does, regardless of the reason.

  46. Solution -module(pmon). -export([start/1, init/1]). start(Pid)-> spawn(pmon, init, [Pid]). init(Pid)-> process_flag(trap_exit, true), link(Pid), loop(Pid). loop(Pid)-> receive {'EXIT', Pid, normal}-> ok; {'EXIT', Pid, Reason} -> io:format("Process ~p terminated abnormally, reason: ~p~n", [Pid, Reason]); _Other -> loop(Pid) end.

  47. Master and Slaves • Write a module ms that has the following interfaces: • start(N): starts a master process and tells it to start N slave processes. Register the master as master. • to_slave(Message, N): Sends a message to the master and tell it to relay the message to slave N. • The slave should exit if it receives the message die. • The master should restart the dead slave and restarts it.

  48. Master and slaves • ms:start(4). • true • ms:to_slave(hello, 2). • {hello, 2} • Slave 2 got message hello. • ms:to_slave(die, 3). • {die, 3} • master restarting dead slave 3.

  49. Solution -module(ms). -export([start/1, to_slave/2]). -export([master_init/1, slave_init/1]). start(N)-> spawn(ms, master_init, [N]). to_slave(Msg, N)-> master ! {to_slave, self(), Msg, N}. master_init(N)-> register(master, self()), process_flag(trap_exit, true), Slaves = start_slaves(N, []), master_loop(Slaves).

  50. Solution start_slaves(0, Slaves)-> Slaves; start_slaves(N, Slaves) -> start_slaves(N-1, [spawn_link(ms, slave_init, [N])|Slaves]).

More Related