Concurrency patterns revisited

Message passing

Barrier synchronisation revisited

code

Barrier synchronization

reach_wait(Server) ->
    Ref = make_ref(), 
    Server ! {reach, self(), Ref},
    receive 
       {ack, Ref} -> true
    end. 

start(N) -> 
    Pid = spawn(fun() -> coordinator(N,N,[]) end),
    register(coordinator, Pid).


coordinator(N,0,Ps) ->
    [ From ! {ack, Ref} || {From, Ref} <- Ps ],
    coordinator(N,N,[]) ;

coordinator(N,M,Ps) ->
    receive 
        {reach, From, Ref} -> 
                 coordinator(N,M-1, [ {From,Ref} | Ps]) 
    end.

Resource allocation revisited

code

loop(Resources) ->
    Available = length(Resources),
    receive 
       {req, From, Ref, Number} when Number =< Available ->
            From ! {res, Ref, lists:sublist(Resources, Number)},
            loop(lists:sublist(Resources, Number+1, Available)) ;

       {ret, List} -> loop(lists:append(Resources, List))
    end.      

start(Init) ->
    Pid = spawn (fun () -> loop(Init) end),
    register(rserver, Pid).


request(N) ->
    Ref = make_ref(),    
    rserver ! {req, self(), Ref, N},
    receive 
        {res, Ref, List} -> List
    end.

release(List) ->
    rserver ! {ret, List},
    ok
> c(ralloc).
{ok,ralloc}
> ralloc:start([1,1,1,1]).
true
> ralloc:request(3).
[1,1,1]
> ralloc:release([1]).
ok
> ralloc:request(2).
[1,1]
> ralloc:request(10).

Readers and writers revisited

loop(Rs, Ws) ->
    receive
       {start_read, From, Ref} when Ws =:= 0 -> 
            From ! {ok_to_read, Ref},
            loop(Rs+1,Ws) ;

       {start_write, From, Ref} when Ws =:= 0 and Rs =:= 0 ->
            From ! {ok_to_write, Ref},
            loop(Rs, Ws+1) ;

       end_read  -> loop(Rs-1, Ws) ;

       end_write -> loop(Rs, Ws-1)
    end.      

Fair readers and writers

code

Fair
readers/writers

loop() ->
    receive
       {start_read, From, Ref} -> 
            From ! {ok_to_read, Ref},
            loop_read(1),
            loop() ;

       {start_write, From, Ref} ->
            From ! {ok_to_write, Ref},
            receive 
                end_write -> loop() 
            end 
    end.      

loop_read(0) -> ok ;
loop_read(Rs) ->
    receive 
       {start_read, From, Ref} ->  
            From ! {ok_to_read, Ref},
            loop_read(Rs+1) ;

       end_read -> loop_read(Rs-1) ;

       {start_write, From, Ref} ->
            [ receive end_read -> ok end 
              || _ <- lists:seq(1,Rs) ],
            From ! {ok_to_write, Ref},
            receive 
                   end_write -> ok 
            end
     end.