syntax: 'meth' -> 'fun', 'attr' -> 'var'
[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 fun to_s: String
19 do
20 return _name
21 end
22 var _name: String = "noname"
23 end
24
25 class WakeUpNode
26 special Node
27 fun wake_up is abstract
28 # Wake up the node
29 fun 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 var _scheduler: Scheduler
35 end
36
37 class NodeSource
38 special Node
39 var _nexts: nullable ArraySet[NodeSink] = null
40 fun 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 fun 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 fun 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.as(not null) do
67 n.recieve(self)
68 end
69 end
70 end
71
72 class NodeSink
73 special Node
74 fun recieve(n: NodeSource) is abstract
75 # the `n' has emeted a signal
76 end
77
78 #
79
80 class Scheduler
81 var _time_list: Array[Couple[Int, WakeUpNode]] = new Array[Couple[Int, WakeUpNode]]
82 var _time: Int = 0 # What time is it ?
83 fun 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 fun next_event: nullable 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 fun 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 end
129 end
130
131 #
132
133 class BeepSource
134 special NodeSource
135 special WakeUpNode
136 redef fun wake_up
137 do
138 send
139 wake_up_in(_delay)
140 end
141 var _delay: Int
142 fun start
143 do
144 wake_up_in(_delay)
145 end
146
147 init(name: String, s: Scheduler, delay: Int)
148 do
149 _name = name
150 _scheduler = s
151 _delay = delay
152 end
153 end
154
155 class CountSink
156 special NodeSink
157 readable var _count: Int = 0
158 redef fun recieve(n: NodeSource)
159 do
160 _count = _count + 1
161 end
162 end
163
164 class SimpleCountSink
165 special CountSink
166
167 init(name: String)
168 do
169 _name = name
170 end
171 end
172
173 class NodeAlternate
174 special NodeSink
175 special NodeSource
176 var _last: nullable NodeSource
177 redef fun recieve(n: NodeSource)
178 do
179 if n != _last then
180 _last = n
181 send
182 end
183 end
184
185 init(name: String)
186 do
187 _name = name
188 end
189 end
190
191 class NodeEat
192 special CountSink
193 special NodeSource
194 var _limit: Int
195 redef fun recieve(n: NodeSource)
196 do
197 var c = _count + 1
198 if c >= _limit then
199 _count = 0
200 send
201 else
202 _count = c
203 end
204 end
205
206 init(name: String, limit: Int)
207 do
208 _name = name
209 _limit = limit
210 end
211 end
212
213 class NodeDelay
214 special NodeSource
215 special NodeSink
216 special WakeUpNode
217 var _delay: Int
218 redef fun recieve(n: NodeSource)
219 do
220 wake_up_in(_delay)
221 end
222 redef fun wake_up
223 do
224 send
225 end
226
227 init(name: String, scheduler: Scheduler, delay: Int)
228 do
229 _name = name
230 _scheduler = scheduler
231 _delay = delay
232 end
233 end
234
235 #
236
237 var s = new Scheduler
238
239 var b1 = new BeepSource("Beep 1", s, 10)
240 var b2 = new BeepSource("Beep 2", s, 7)
241 var a1 = new NodeAlternate("Alternate 1")
242 var a2 = new NodeAlternate("Alternate 2")
243 var a3 = new NodeAlternate("Alternate 3")
244 var d1 = new NodeDelay("Delay 1", s, 2)
245 var e1 = new NodeEat("Eat 1", 5)
246 var c1 = new SimpleCountSink("Count 1")
247 b1.attach(a1)
248 b1.attach(a3)
249
250 b2.attach(a1)
251 b2.attach(a2)
252
253 b2.attach(a3)
254
255 a1.attach(e1)
256 a1.attach(a2)
257
258 a2.attach(a2)
259 a2.attach(a3)
260
261 a3.attach(e1)
262 a3.attach(d1)
263
264 d1.attach(e1)
265
266 e1.attach(c1)
267 e1.attach(a1)
268
269 b1.start
270 b2.start
271
272 var nb = 100000
273 if not args.is_empty then
274 nb = args.first.to_i
275 end
276
277 s.run_for(nb)
278 print(c1.count)
279