-module(barrier).
-export([example/1]).


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.


%% Example 
p(I) ->
     timer:sleep(random:uniform(1000)),
     io:format("Process ~w has reached the barrier!~n",[I]),
     reach_wait(coordinator),  
     io:format("Process ~w leaves the barrier~n",[I]).

example(N) -> 
    start(N), 
    [ spawn (fun () -> p(X), p(X) end) || X <- lists:seq(1,N) ].