Concurrency


Processes

code

Passing a value

  test1(N) ->
    P = self(),
    Pid = spawn(messages, run, [P]),
    io:format("Spawned ~p~n",[Pid]),
    io:format("Sending ~p~n",[N]),
    Pid!{msg1, N},
    receive
      {msg2, M} ->
         io:format("Received back ~p~n",[M])
    end.

  run(P) ->
    io:format("Hello!~n"),
    receive
      {msg1, N} ->
        io:format("Received ~p~n",[N]),
        io:format("Sending back ~p~n",[N+1]),
        P!{msg2, N+1}
    end.

Mailboxes (message queues)

A simple echo-server

code

Indirect

-module(echo).
-export([start/0, echo/0]).

echo() ->
  receive
    {From, Msg} -> 
      From ! {self(), Msg},
      echo();
    stop ->
      true
  end.

start() ->
  Pid = spawn(fun echo/0),
  % sending tokens to the server
  Token = 42, 
  Pid ! {self(), Token},
  io:format("Sent~w~n",[Token]),
  receive 
    {Pid, Msg} ->
      io:format("Received ~w~n", [Msg]) 
  end,
  % stop server
  Pid ! stop.    

Client-Server Architecture

Mathematical server

code

Sources of multiple messages

Registered processes

code

Distributed environments

Distributed mathematical server

Forking

Message passing

How does it work?

Forms of synchronization

Consider the behaviour of the sender of a message

Examples

Forms of naming

How do sender and receiver refer to each other when message passing is used?

Erlang message passing


Exceptions

List comprehensions

1> [ X + 2 || X <- [2, 4, 5]].
[4,6,7]
2> [ X + Y * 10 || X <- [2, 4, 5], Y <- [1, 4]].
[12,42,14,44,15,45]
3> [ X + 2 || X <- [2, 4, 5], X > 3].
[6,7]
4> [ io:format("~p~n", [X]) || X <- [apple, pear, orange]].
apple
pear
orange
[ok,ok,ok]
5> [ {X, Y} || X <- [2, 3, 4], Y <- lists:seq(1, X)].      
[{2,1},{2,2},{3,1},{3,2},{3,3},{4,1},{4,2},{4,3},{4,4}]
6> [ {X, Y} || Y <- lists:seq(1, X), X <- [2, 3, 4]].       
* 1: variable 'X' is unbound
7> [ {X, Y} || X <- [2, 3, 4], Y <- lists:seq(1, X), Y > 1].
[{2,2},{3,2},{3,3},{4,2},{4,3},{4,4}]
8> [ {X, Y} || X <- [2, 3, 4], Y > 1, Y <- lists:seq(1, X)].
* 1: variable 'Y' is unbound

Lambda expressions

f() -> io:format("new process created!~n").

test() -> spawn(fun f/0).
f() -> io:format("new process created!~n").

test() -> spawn(fun () -> io:format("new process created!~n") end).

Higher-order functions

sum([])     -> 0;
sum([X|Xs]) -> X + sum(Xs).

mul([])     -> 1;
mul([X|Xs]) -> X * mul(Xs).
reduce(_, E, [])     -> E;
reduce(F, E, [X|Xs]) -> F (X, reduce(F, E, Xs)).

sum2(L) -> reduce(fun(X, Y) -> X + Y end, 0, L).
mul2(L) -> reduce(fun(X, Y) -> X * Y end, 1, L).
append(L1, L2) -> reduce(fun(X, Y) -> [X|Y] end, L2, L1).

Begin-end blocks

f(a, b, begin io:format("hello~n"), c end)


Concurrent Programming 2016 - Chalmers University of Technology & Gothenburg University