First NIT release and new clean mercurial repository
[nit.git] / tests / bench_netsim.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2005-2008 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 class Node
18 redef meth to_s: String
19 do
20 return _name
21 end
22 attr _name: String
23 end
24
25 class WakeUpNode
26 special Node
27 meth wake_up is abstract
28 # Wake up the node
29 meth wake_up_in(d: Int)
30 # Ask to be weaked up in `d' time units
31 do
32 _scheduler.add_event(self, d)
33 end
34 attr _scheduler: Scheduler
35 end
36
37 class NodeSource
38 special Node
39 attr _nexts: ArraySet[NodeSink]
40 meth attach(n: NodeSink)
41 # Add the sink `n' the the connected nodes
42 # Do nothing if `n' is already connected
43 do
44 assert n != null
45 # Create the collection if needed
46 if _nexts == null then
47 _nexts = new ArraySet[NodeSink]
48 end
49 _nexts.add(n)
50 end
51
52 meth detach(n: NodeSink)
53 # Remove the sink `n' from the connected nodes
54 # Do nothing if `n' is not connected
55 do
56 assert n != null
57 _nexts.remove(n)
58 end
59
60 protected meth send
61 # Notify the sinks by calling the recieve(1) method of each sink
62 do
63 if _nexts == null then
64 return
65 end
66 for n in _nexts do
67 n.recieve(self)
68 end
69 end
70 end
71
72 class NodeSink
73 special Node
74 meth recieve(n: NodeSource) is abstract
75 # the `n' has emeted a signal
76 end
77
78 #
79
80 class Scheduler
81 attr _time_list: Array[Couple[Int, WakeUpNode]]
82 attr _time: Int # What time is it ?
83 meth add_event(n: WakeUpNode, d: Int)
84 # The node `n' whant to be weaked up in `d' time units
85 do
86 var entry = new Couple[Int, WakeUpNode](d+_time, n)
87 _time_list.add(entry)
88 end
89
90 meth next_event: WakeUpNode
91 # Get the
92 do
93 if _time_list.is_empty then
94 return null
95 end
96
97 # Get the next entry
98 var entry = _time_list.first
99 for e in _time_list do
100 if e.first < entry.first then
101 entry = e
102 end
103 end
104 _time_list.remove(entry)
105
106 _time = entry.first
107 return entry.second
108 end
109
110 meth run_for(time_limit: Int)
111 do
112 while true do
113 var node = next_event
114 if _time > time_limit then
115 print("Time limit.")
116 return
117 end
118 if node == null then
119 print("No more event.")
120 return
121 end
122 node.wake_up
123 end
124 end
125
126 init
127 do
128 _time_list = new Array[Couple[Int, WakeUpNode]]
129 end
130 end
131
132 #
133
134 class BeepSource
135 special NodeSource
136 special WakeUpNode
137 redef meth wake_up
138 do
139 send
140 wake_up_in(_delay)
141 end
142 attr _delay: Int
143 meth start
144 do
145 wake_up_in(_delay)
146 end
147
148 init(name: String, s: Scheduler, delay: Int)
149 do
150 _name = name
151 _scheduler = s
152 _delay = delay
153 end
154 end
155
156 class CountSink
157 special NodeSink
158 readable attr _count: Int
159 redef meth recieve(n: NodeSource)
160 do
161 _count = _count + 1
162 end
163 end
164
165 class SimpleCountSink
166 special CountSink
167
168 init(name: String)
169 do
170 _name = name
171 end
172 end
173
174 class NodeAlternate
175 special NodeSink
176 special NodeSource
177 attr _last: NodeSource
178 redef meth recieve(n: NodeSource)
179 do
180 if n != _last then
181 _last = n
182 send
183 end
184 end
185
186 init(name: String)
187 do
188 _name = name
189 end
190 end
191
192 class NodeEat
193 special CountSink
194 special NodeSource
195 attr _limit: Int
196 redef meth recieve(n: NodeSource)
197 do
198 var c = _count + 1
199 if c >= _limit then
200 _count = 0
201 send
202 else
203 _count = c
204 end
205 end
206
207 init(name: String, limit: Int)
208 do
209 _name = name
210 _limit = limit
211 end
212 end
213
214 class NodeDelay
215 special NodeSource
216 special NodeSink
217 special WakeUpNode
218 attr _delay: Int
219 redef meth recieve(n: NodeSource)
220 do
221 wake_up_in(_delay)
222 end
223 redef meth wake_up
224 do
225 send
226 end
227
228 init(name: String, scheduler: Scheduler, delay: Int)
229 do
230 _name = name
231 _scheduler = scheduler
232 _delay = delay
233 end
234 end
235
236 #
237
238 var s = new Scheduler
239
240 var b1 = new BeepSource("Beep 1", s, 10)
241 var b2 = new BeepSource("Beep 2", s, 7)
242 var a1 = new NodeAlternate("Alternate 1")
243 var a2 = new NodeAlternate("Alternate 2")
244 var a3 = new NodeAlternate("Alternate 3")
245 var d1 = new NodeDelay("Delay 1", s, 2)
246 var e1 = new NodeEat("Eat 1", 5)
247 var c1 = new SimpleCountSink("Count 1")
248 b1.attach(a1)
249 b1.attach(a3)
250
251 b2.attach(a1)
252 b2.attach(a2)
253
254 b2.attach(a3)
255
256 a1.attach(e1)
257 a1.attach(a2)
258
259 a2.attach(a2)
260 a2.attach(a3)
261
262 a3.attach(e1)
263 a3.attach(d1)
264
265 d1.attach(e1)
266
267 e1.attach(c1)
268 e1.attach(a1)
269
270 b1.start
271 b2.start
272
273 var nb = 100000
274 if not args.is_empty then
275 nb = args.first.to_i
276 end
277
278 s.run_for(nb)
279 print(c1.count)
280