Commit | Line | Data |
---|---|---|
d2a0e2f9 SK |
1 | -module(cell). |
2 | -behaviour(gen_server). | |
3 | ||
4 | ||
5 | %% API | |
6 | -export([start_link/1]). | |
7 | ||
8 | %% Callbacks | |
9 | -export([init/1 | |
10 | ,handle_call/3 | |
11 | ,handle_cast/2 | |
12 | ,handle_info/2 | |
13 | ,terminate/2 | |
14 | ,code_change/3 | |
15 | ]). | |
16 | ||
17 | ||
18 | -record(state, {id :: integer() | |
19 | ,name :: string() | |
20 | ,cell_state :: 0 | 1 | |
21 | ,neighbors :: list(atom()) | |
22 | ,live_neighbors :: integer() | |
23 | ,num_neighbors :: integer() | |
24 | ,replies_pending :: integer() | |
25 | }). | |
26 | ||
27 | ||
28 | %% ============================================================================ | |
29 | %% API | |
30 | %% ============================================================================ | |
31 | ||
32 | start_link({_ID, Name, _NeighborNames}=Datum) -> | |
33 | ServerName = {local, Name}, | |
34 | Args = [Datum], | |
35 | Opts = [], | |
36 | gen_server:start_link(ServerName, ?MODULE, Args, Opts). | |
37 | ||
38 | ||
39 | %% ============================================================================ | |
40 | %% Callbacks | |
41 | %% ============================================================================ | |
42 | ||
43 | init([{ID, Name, NeighborNames}]) -> | |
44 | State = #state{id=ID | |
45 | ,name=Name | |
46 | ,cell_state=crypto:rand_uniform(0, 2) | |
47 | ,neighbors=NeighborNames | |
48 | ,num_neighbors=length(NeighborNames) | |
49 | ,live_neighbors=0 | |
50 | ,replies_pending=0 | |
51 | }, | |
52 | {ok, State}. | |
53 | ||
54 | ||
55 | terminate(_Reason, State) -> | |
56 | {ok, State}. | |
57 | ||
58 | ||
59 | code_change(_Old, State, _Other) -> | |
60 | {ok, State}. | |
61 | ||
62 | ||
63 | handle_call(_Msg, _From, State) -> | |
64 | {reply, ok, State}. | |
65 | ||
66 | ||
67 | handle_cast(_Msg, State) -> | |
68 | {noreply, State}. | |
69 | ||
70 | ||
71 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
72 | ||
73 | handle_info(tick, | |
74 | #state{name=Name | |
75 | ,neighbors=Neighbors | |
76 | ,num_neighbors=NumNeighbors | |
77 | }=State) -> | |
78 | ||
79 | ok = send_all(Neighbors, {request_state, Name}), | |
80 | {noreply, State#state{replies_pending=NumNeighbors}}; | |
81 | ||
82 | ||
83 | handle_info({request_state, Requester}, State) -> | |
84 | Requester ! {response_state, State#state.cell_state}, | |
85 | {noreply, State}; | |
86 | ||
87 | ||
88 | handle_info({response_state, NeighborState}, | |
89 | #state{id=ID | |
90 | ,replies_pending=Pending | |
91 | ,cell_state=CellState | |
92 | ,live_neighbors=LiveNeighbors | |
93 | }=State) -> | |
94 | ||
95 | NewPending = Pending - 1, | |
96 | NewLiveNeighbors = LiveNeighbors + NeighborState, | |
97 | ||
98 | NewState = State#state{replies_pending=NewPending | |
99 | ,live_neighbors=NewLiveNeighbors | |
100 | }, | |
101 | ||
102 | case NewPending of | |
103 | 0 -> | |
104 | NewCellState = new_state(CellState, NewLiveNeighbors), | |
105 | ok = time:cast({tock, {ID, NewCellState}}), | |
106 | ||
107 | {noreply, NewState#state{live_neighbors=0 | |
108 | ,cell_state=NewCellState | |
109 | }}; | |
110 | ||
111 | _N -> | |
112 | {noreply, NewState} | |
113 | end; | |
114 | ||
115 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
116 | ||
117 | ||
118 | handle_info(_Msg, State) -> | |
119 | {noreply, State}. | |
120 | ||
121 | ||
122 | %% ============================================================================ | |
123 | %% Internal | |
124 | %% ============================================================================ | |
125 | ||
126 | send_all([], _) -> ok; | |
127 | send_all([PID | PIDs], Msg) -> | |
128 | PID ! Msg, | |
129 | send_all(PIDs, Msg). | |
130 | ||
131 | ||
132 | new_state(1, LiveNeighbors) when LiveNeighbors < 2 -> 0; | |
133 | new_state(1, LiveNeighbors) when LiveNeighbors < 4 -> 1; | |
134 | new_state(1, LiveNeighbors) when LiveNeighbors > 3 -> 0; | |
135 | new_state(0, LiveNeighbors) when LiveNeighbors =:= 3 -> 1; | |
136 | new_state(State, _LiveNeighbors) -> State. |