2 -behaviour(gen_server).
6 -export([start_link/1]).
18 -record(state, {id :: integer()
21 ,neighbors :: list(atom())
22 ,live_neighbors :: integer()
23 ,num_neighbors :: integer()
24 ,replies_pending :: integer()
29 %% ============================================================================
31 %% ============================================================================
33 start_link({_ID, Name, _NeighborNames}=Datum) ->
34 ServerName = {local, Name},
37 gen_server:start_link(ServerName, ?MODULE, Args, Opts).
40 %% ============================================================================
42 %% ============================================================================
44 init([{ID, Name, NeighborNames}]) ->
45 State = #state{id = ID
47 ,cell_state = crypto:rand_uniform(0, 2)
48 ,neighbors = NeighborNames
49 ,num_neighbors = length(NeighborNames)
56 terminate(_Reason, State) ->
60 code_change(_Old, State, _Other) ->
64 handle_call(_Msg, _From, State) ->
68 handle_cast({next_gen, GenID},
71 ,num_neighbors=NumNeighbors
73 ok = cast_all(Neighbors, {request_state, Name}),
74 {noreply, State#state{replies_pending=NumNeighbors, gen_id=GenID}};
77 handle_cast({request_state, Requester}, State) ->
78 ok = gen_server:cast(Requester, {response_state, State#state.cell_state}),
82 handle_cast({response_state, NeighborState},
84 ,replies_pending=Pending
86 ,live_neighbors=LiveNeighbors
89 NewPending = Pending - 1,
90 NewLiveNeighbors = LiveNeighbors + NeighborState,
92 NewState = State#state{replies_pending=NewPending
93 ,live_neighbors=NewLiveNeighbors
98 NewCellState = new_state(CellState, NewLiveNeighbors),
99 ok = life_time:report_state(ID, NewCellState),
101 {noreply, NewState#state{live_neighbors=0
102 ,cell_state=NewCellState
111 handle_cast(_Msg, State) ->
115 handle_info(_Msg, State) ->
119 %% ============================================================================
121 %% ============================================================================
123 cast_all([], _) -> ok;
124 cast_all([Server | Servers], Msg) ->
125 ok = gen_server:cast(Server, Msg),
126 cast_all(Servers, Msg).
129 new_state(1, LiveNeighbors) when LiveNeighbors < 2 -> 0;
130 new_state(1, LiveNeighbors) when LiveNeighbors < 4 -> 1;
131 new_state(1, LiveNeighbors) when LiveNeighbors > 3 -> 0;
132 new_state(0, LiveNeighbors) when LiveNeighbors =:= 3 -> 1;
133 new_state(State, _LiveNeighbors) -> State.