380 likes | 434 Views
Erlang. Erricsson and Ellemtel Computer Science Laboratories http://www.erlang.org Heather Conboy and Shangzhu Wang University of Massachusetts Amherst. What is Erlang for ?. For programming concurrent , real-time , and distributed fault-tolerant systems. Erlang Highlights.
E N D
Erlang Erricsson and Ellemtel Computer Science Laboratories http://www.erlang.org Heather Conboy and Shangzhu Wang University of Massachusetts Amherst
What is Erlang for ? For programming concurrent, real-time, and distributed fault-tolerant systems
Erlang Highlights • Declarative • High abstraction level • Dynamic data typing • Single assignment variables • Pattern matching (symbolic) • Real time garbage collection • Concurrency • Robustness • Distribution
A Sequential Erlang Program • Module • Function • Variable • Atom • Tuple • List • Record -module(tut1). -export([fac/1, mult/2, area/1], list_len/1, new_person/2). -record(person, {name, age}). fac(1) -> 1; fac(N) -> N * fac(N - 1). mult(X, Y) -> X * Y. area({square, Side}) -> Side * Side; area({circle, Radius}) -> 3 * Radius * Radius; area(Other) -> {invalid_object, Other}. list_length([]) -> 0; list_length([First | Rest]) -> 1 + list_length(Rest). new_person(Name, Age) -> #person{name=Name, age=Age}. > c(tut1). > tut1:area({square,3}). > 9 Pattern matching
Erlang Highlights • Declarative • Concurrency • Simple abstraction • Massive concurrency and lightweight processes • Efficient message passing (asynchronous) • Processes share nothing • Robustness • Distribution
Creating a New Process Pid2 = spawn(Mod, Fun, Args). %Pid2 is only known to Pid1 register(myprocessname, Pid2). unregister(myprocessname). whereis(myprocessname). registered().
Creating a New Process (an example) -module(tut2). -export([start/0, say_something/2]). say_something(What, 0) -> done; say_something(What, Times) -> io:format ("~p~n", [What]), say_something(What, Times - 1). start() -> spawn(tut2, say_something, [hello, 3]), spawn(tut2, say_something, [goodbye, 3]).
Message Passing From and Msg become bound when the message is received (From = A, Msg = foo) Wildcard message passing Selective message passing
Message Passing – an echo process -module(echo). -export([go/0, loop/0]). go() -> Pid2 = spawn(echo, loop, []), Pid2 ! {self(), hello}, receive {Pid2, Msg} -> io:format("P1 ~w~n",[Msg]) end, Pid2 ! stop. loop() -> receive {From, Msg} -> From ! {self(), Msg}, loop(); stop -> true end. {A, Msg} A B Msg A B
Message Passing – Guards and Timeouts • Receive operations can have boolean guards • In fact, functions, too. • Timeout • after infinity • after 0 receive -> msg1 when BoolExp -> … msg2 -> … after 5000 -> … end.
Processes - Micellanies • Process scheduling • process_flag(priority, Pri) • Pri = normal/low • Process groups • All Erlang processes are arranged in a tree • group_leader(), group_leader(Leader, Pid) • Process dictionary • Local to each process
A Banking Example -module(bank_server). -export([start/0, server/1]). start() -> register(bank_server, spawn(bank_server, server, [[]])). server(Data) -> receive {From, {deposit, Who, Amount}} -> From ! {bank_server, ok}, server(deposit(Who, Amount, Data)); {From, {ask, Who}} -> From ! {bank_server, lookup(Who, Data)}, server(Data); {From, {withdraw, Who, Amount}} -> case lookup(Who, Data) of undefined -> From ! {bank_server, no}, server(Data); Balance when Balance > Amount -> From ! {bank_server, ok}, server(deposit(Who, -Amount, Data)); _ -> From ! {bank_server, no}, server(Data) end end. A Concurrent Banking Example bank_server
A Banking Example (cont’d) A Concurrent Banking Example bank_client -module(bank_client). -export([ask/1, deposit/2, withdraw/2]). ask(Who) -> call_bank({ask, Who}). deposit(Who, Amount) -> call_bank({deposit, Who, Amount}). withdraw(Who, Amount) -> call_bank({withdraw, Who, Amount}). call_bank(Msg) -> bank_server ! {self(), Msg}, receive {bank_server, Reply} -> Reply end.
A Banking Example (cont’d) A Concurrent Banking Example bank_client -module(bank_client). -export([ask/1, deposit/2, withdraw/2]). ask(Who) -> call_bank({ask, Who}). deposit(Who, Amount) -> call_bank({deposit, Who, Amount}). withdraw(Who, Amount) -> call_bank({withdraw, Who, Amount}). call_bank(Msg) -> bank_server ! {self(), Msg}, receive {bank_server, Reply} -> Reply end. What if the client or server crashes?
Erlang Highlights • Declarative • Concurrency • Robustness • Explicit error handling mechanisms • Allow errors to be caught, propagated, trapped • Distribution
Types of Errors • A match operation may fail • A BIF may be evaluated with incorrect arguments • Arithmetic expression errors • A process may crash • …
Error Handling Mechanisms • Monitoring the evaluation of an expression • catch, throw • Monitoring the behavior of other processes • link/1, spawn_link/3 • process_flag(trap_exit, true) • Trapping evaluation of undefined functions • error_handler:undefined_call(Module, Func, Args)
Catch and Throw • Protecting sequential code from errors (catchExpression) • If there is an evaluation error, returns {‘Exit’, Reason} • Otherwise, returns the value of Expression • Exit directly from a function with an error (catch combined with throw) demo(X) -> case catch foo(X) of {myerror, Args} -> throw({user_error, Args}); {'EXIT', What} -> throw({caught_error, What}); Other -> Other end. foo(1) -> hello; foo(2) -> throw({myerror, abc}); foo(3) -> tuple_to_list(a); foo(4) -> exit({myExit, 222}).
Termination of processes • Termination of Erlang processes • Normal exit • exit(normal) • runs out of things to do • Abnormal exit • When encounters a runtime error • exit(Reason) • Links (bidirectional) • link(Other_pid), spawn_link • When a process terminates it sends a signal (pid and reason) to all the processes it’s linked with • A normal exit signal gets ignored (by default) • An abnormal exit signal gets propagated, processes linked are killed, messages are dropped • Exit signals can be trapped by a receiving process • process_flag(trap_exit, true)
Error Propagation and Trapping Error trapping receive {'EXIT', P1, Why} -> ... end Error propagation
Error Handling in Layers Error management in layers
The Banking Example with Error Handling -module(bank_server). -export([start/0, start_server/1]). start() -> register(bank_server, spawn(bank_server, start_server, [[]])). start_server(Data) -> process_flag(trap_exit, true), server(Data). server(Data) -> receive {From, {deposit, Who, Amount}} -> link(From), From ! {bank_server, ok}, server(deposit(Who, Amount, Data)); {From, {ask, Who}} -> link(From), From ! {bank_server, lookup(Who, Data)}, server(Data); {From, {withdraw, Who, Amount}} -> link(From), case lookup(Who, Data) of … end {‘EXIT’, From, _} -> unlink(From), io:format(“Bank client ~p is down.~n”, [From]), server(Data) end. A Concurrent Banking Example with error handling the server
Trapping Evaluation of Undefined Functions • The error_handler module • error_handler:undefined_call(Module, Func, Args) is called when an undefined function is called • Specialized error handler module can be defined • Set process_flag(error_handler, MyErrorHandlerModule) • Then, MyErrorHandlerModule:underfined_call will be called instead
Erlang Highlights • Declarative • Concurrency • Robustness • Distribution • Transparent distribution • Run on a network of Erlang nodes
Distributed Programming • System runs on a network of Erlang nodes • nodes: an executing Erlang system which can take part in distributed transactions • Create processes on a specific node
Distributed Programming - BIFs • spawn(Node, Mod, Func, Args) • spawn_link(Node, Mod, Func, Args) • monitor_node(Node, Flag) • be notified with a {nodedown, Node} message if Node fails or if the network connection to Node fails. • node() • Returns our own node name. • nodes() • Returns a list of the other known node names. • node(Item) • Returns the node name of the origin of Item where Item can be a Pid, reference or a port. • disconnect_node(Nodename) • Disconnects us from the node Nodename.
Distributing the Banking Example -module(bank_server). -export([start/0, server/1]). start() -> register(bank_server, spawn(bank_server, start_server, [[]])). start_server(Data) -> process_flag(trap_exit, true), server(Data). server(Data) -> receive {From, {deposit, Who, Amount}} -> link(From), From ! {bank_server, ok}, server(deposit(Who, Amount, Data)); {From, {ask, Who}} -> link(From), From ! {bank_server, lookup(Who, Data)}, server(Data); {From, {withdraw, Who, Amount}} -> link(From), case lookup(Who, Data) of … end {‘EXIT’, From, _} -> unlink(From), io:format(“Bank client ~p is down.~n”, [From]), server(Data) end. A Distributed Banking Example The server
Distributing the Banking Example -module(bank_client). -export([ask/1, deposit/2, withdraw/2]). head_office() -> 'bank_server@super.eua.ericsson.se'. ask(Who) -> call_bank({ask, Who}). deposit(Who, Amount) -> call_bank({deposit, Who, Amount}). withdraw(Who, Amount) -> call_bank({withdraw, Who, Amount}). call_bank(Msg) -> Headoffice = head_office(), {bank_server, Headoffice} ! {self(), Msg}, receive {bank_server, Reply} -> Reply end. A Distributed Banking Example the client
Distributing the Banking Example A Distributed Banking Example with error handling the client -module(bank_client). -export([ask/1, deposit/2, withdraw/2]). head_office() -> 'bank@super.eua.ericsson.se'. ask(Who) -> call_bank({ask, Who}). deposit(Who, Amount) -> call_bank({deposit, Who, Amount}). withdraw(Who, Amount) -> call_bank({withdraw, Who, Amount}). call_bank(Msg) -> Headoffice = head_office(), monitor_node(Headoffice, true), {bank_server, Headoffice} ! {self(), Msg}, receive {bank_server, Reply} -> monitor_node(Headoffice, false), Reply; {nodedown, Headoffice} -> no end.
Other Erlang Features • Runs on virtual machines • Can be compiled natively • Interpreter • Incremental real-time garbage collector • Support soft real-time programming with responsive time in milliseconds • Hot code loading • Primitives to allow code to be replaced in a running system • Allow old and new versions of code to execute at the same time
Erlang Application Outside world port Other Erlang Features • External interfaces (ports) • Provide byte stream interfaces to external UNIX processes (binary) • Ports act as normal Erlang processes • open_port(Portname, Portsettings)
Other Erlang Features (cont’d) • Last call optimization • Allows functions to be evaluated in constant space • Atail recursive function do not accumulate any pending operations before a recursive call length([_ | T]) -> 1 + length(T); length([]) -> 0. length1(L) -> length1(L, 0). length1([_|T], N) -> length1(T, 1 + N); length1([], N) -> N.
Other Erlang Features (cont’d) • References • R = make_ref(). • Guaranteed globally unique objects • e.g. , can be used as end_to_end confirmation in a client-server model • Binaries • Used to store an area of untyped memory • Can be converted to and from other data types
Erlang Domains • Originally targeted at telecom applications • Massively multi-player online games • Banking system • Robust, scalable web services • Highly multi-threaded user interfaces
References • http://www.erlang.org