OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef BIN_EVENTHANDLER_H_ | 5 #ifndef BIN_EVENTHANDLER_H_ |
6 #define BIN_EVENTHANDLER_H_ | 6 #define BIN_EVENTHANDLER_H_ |
7 | 7 |
8 #include "bin/builtin.h" | 8 #include "bin/builtin.h" |
9 #include "bin/isolate_data.h" | 9 #include "bin/isolate_data.h" |
10 | 10 |
11 #include "platform/hashmap.h" | |
12 | |
11 namespace dart { | 13 namespace dart { |
12 namespace bin { | 14 namespace bin { |
13 | 15 |
14 // Flags used to provide information and actions to the eventhandler | 16 // Flags used to provide information and actions to the eventhandler |
15 // when sending a message about a file descriptor. These flags should | 17 // when sending a message about a file descriptor. These flags should |
16 // be kept in sync with the constants in socket_impl.dart. For more | 18 // be kept in sync with the constants in socket_impl.dart. For more |
17 // information see the comments in socket_impl.dart | 19 // information see the comments in socket_impl.dart |
18 enum MessageFlags { | 20 enum MessageFlags { |
19 kInEvent = 0, | 21 kInEvent = 0, |
20 kOutEvent = 1, | 22 kOutEvent = 1, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
87 UpdateTimeout(CurrentPort(), -1); | 89 UpdateTimeout(CurrentPort(), -1); |
88 } | 90 } |
89 | 91 |
90 void UpdateTimeout(Dart_Port port, int64_t timeout); | 92 void UpdateTimeout(Dart_Port port, int64_t timeout); |
91 | 93 |
92 private: | 94 private: |
93 Timeout* next_timeout_; | 95 Timeout* next_timeout_; |
94 Timeout* timeouts_; | 96 Timeout* timeouts_; |
95 }; | 97 }; |
96 | 98 |
99 | |
100 template<typename T> | |
101 class CircularLinkedList { | |
102 public: | |
103 CircularLinkedList() : head_(NULL) {} | |
104 | |
105 // Returns true if the list was empty. | |
106 bool Add(T t) { | |
107 Entry* e = new Entry(t); | |
108 if (head_ == NULL) { | |
109 // Empty list, make e head, and point to itself. | |
110 e->next_ = e; | |
111 e->prev_ = e; | |
112 head_ = e; | |
113 return true; | |
114 } else { | |
115 // Insert e as the last element in the list. | |
116 e->prev_ = head_->prev_; | |
117 e->next_ = head_; | |
118 e->prev_->next_ = e; | |
119 head_->prev_ = e; | |
120 return false; | |
121 } | |
122 } | |
123 | |
124 void RemoveHead() { | |
125 Entry* e = head_; | |
126 if (e->next_ == e) { | |
127 head_ = NULL; | |
128 } else { | |
129 e->prev_->next_ = e->next_; | |
130 e->next_->prev_ = e->prev_; | |
131 head_ = e->next_; | |
132 } | |
133 delete e; | |
134 } | |
135 | |
136 T head() const { return head_->t; } | |
137 | |
138 bool HasHead() const { | |
139 return head_ != NULL; | |
140 } | |
141 | |
142 void Rotate() { | |
143 head_ = head_->next_; | |
144 } | |
145 | |
146 private: | |
147 struct Entry { | |
148 explicit Entry(const T& t) : t(t) {} | |
149 const T t; | |
150 Entry* next_; | |
151 Entry* prev_; | |
152 }; | |
153 | |
154 Entry* head_; | |
155 }; | |
156 | |
157 | |
158 class DescriptorInfo { | |
159 public: | |
160 explicit DescriptorInfo(intptr_t fd) : fd_(fd), mask_(0) { | |
161 ASSERT(fd_ != -1); | |
162 } | |
163 | |
164 virtual ~DescriptorInfo() { | |
165 mask_ = 0; | |
166 } | |
167 | |
168 intptr_t fd() { return fd_; } | |
169 | |
170 | |
171 // Type of socket. | |
172 | |
173 virtual bool IsListeningSocket() const = 0; | |
174 | |
175 | |
176 // Ports. | |
177 | |
178 virtual bool AddPort(Dart_Port port) = 0; | |
179 | |
180 virtual bool RemovePort(Dart_Port port) = 0; | |
181 | |
182 // Returns the next port which should be used for sending events to. | |
183 virtual Dart_Port NextPort() = 0; | |
184 | |
185 virtual bool HasNextPort() = 0; | |
186 | |
187 | |
188 // Tokens. | |
189 | |
190 // Returns true if the last token was taken. | |
191 virtual bool TakeToken() = 0; | |
192 | |
193 // Returns true if the tokens was 0 before adding. | |
194 virtual bool ReturnTokens(Dart_Port port, int count) = 0; | |
195 | |
196 // Returns true if for any registired Dart_port tokens are available. | |
197 virtual bool HasTokens() const = 0; | |
198 | |
199 | |
200 // Other. | |
201 | |
202 virtual void Close() = 0; | |
203 | |
204 void SetMask(intptr_t mask) { | |
205 mask_ = mask; | |
206 } | |
207 | |
208 intptr_t Mask() { return mask_; } | |
209 | |
210 protected: | |
211 intptr_t fd_; | |
212 // Mask of events to report through the port. | |
213 intptr_t mask_; | |
214 }; | |
215 | |
216 | |
217 // Describes a OS descriptor (e.g. file descriptor on linux or HANDLE on | |
218 // windows) which is connected to a single Dart_Port. | |
219 // | |
220 // Subclasses of this class can be e.g. connected tcp sockets | |
221 template<typename SI> | |
222 class DescriptorInfoSingle : public SI { | |
223 public: | |
224 explicit DescriptorInfoSingle(intptr_t fd) : SI(fd), port_(0), tokens_(16) { | |
225 } | |
226 | |
227 virtual ~DescriptorInfoSingle() { } | |
228 | |
229 virtual bool IsListeningSocket() const { return false; } | |
230 | |
231 virtual bool AddPort(Dart_Port port) { | |
232 ASSERT(port_ == 0 || port == port_); | |
Søren Gjesse
2015/02/02 10:56:14
This assert looks strange. Are we adding the same
kustermann
2015/02/03 10:45:35
I think so, I've observed this on windows I think.
| |
233 port_ = port; | |
234 return true; | |
235 } | |
236 | |
237 virtual bool RemovePort(Dart_Port port) { | |
238 ASSERT(port_ == 0 || port_ == port); | |
Søren Gjesse
2015/02/02 10:56:14
Again, are we removing a port which is not added?
kustermann
2015/02/03 10:45:35
ditto. I'll add a TODO.
If you want, I can also v
| |
239 port_ = 0; | |
240 return true; | |
241 } | |
242 | |
243 virtual Dart_Port NextPort() { | |
244 ASSERT(port_ != 0); | |
245 return port_; | |
246 } | |
247 | |
248 virtual bool HasNextPort() { | |
249 return port_ != 0; | |
250 } | |
251 | |
252 virtual bool TakeToken() { | |
253 ASSERT(tokens_ > 0); | |
254 tokens_--; | |
255 return tokens_ == 0; | |
256 } | |
257 | |
258 virtual bool ReturnTokens(Dart_Port port, int count) { | |
259 ASSERT(port_ == port); | |
260 ASSERT(tokens_ >= 0); | |
261 bool was_empty = tokens_ == 0; | |
262 tokens_ += count; | |
263 return was_empty; | |
264 } | |
265 | |
266 virtual bool HasTokens() const { return tokens_ > 0; } | |
267 | |
268 virtual void Close() { | |
269 SI::Close(); | |
270 } | |
271 | |
272 private: | |
273 Dart_Port port_; | |
274 int tokens_; | |
275 }; | |
276 | |
277 | |
278 // Describes a OS descriptor (e.g. file descriptor on linux or HANDLE on | |
279 // windows) which is connected to multiple Dart_Port's. | |
280 // | |
281 // Subclasses of this class can be e.g. a listening socket which multiple | |
282 // isolates are listening on. | |
283 template<typename SI> | |
284 class DescriptorInfoMultiple : public SI { | |
285 private: | |
286 static const int kTokenCount = 4; | |
287 | |
288 static bool SamePortValue(void* key1, void* key2) { | |
289 return reinterpret_cast<Dart_Port>(key1) == | |
290 reinterpret_cast<Dart_Port>(key2); | |
291 } | |
292 | |
293 static uint32_t GetHashmapHashFromPort(Dart_Port port) { | |
294 return static_cast<uint32_t>(port & 0xFFFFFFFF); | |
295 } | |
296 | |
297 static void* GetHashmapKeyFromPort(Dart_Port port) { | |
298 return reinterpret_cast<void*>(port); | |
299 } | |
300 | |
301 public: | |
302 explicit DescriptorInfoMultiple(intptr_t fd) | |
303 : SI(fd), tokens_map_(&SamePortValue, 4) {} | |
304 | |
305 virtual ~DescriptorInfoMultiple() {} | |
306 | |
307 virtual bool IsListeningSocket() const { return true; } | |
308 | |
309 virtual bool AddPort(Dart_Port port) { | |
310 HashMap::Entry* entry = tokens_map_.Lookup( | |
311 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), true); | |
312 entry->value = reinterpret_cast<void*>(kTokenCount); | |
313 return live_ports_.Add(port); | |
314 } | |
315 | |
316 virtual bool RemovePort(Dart_Port port) { | |
317 HashMap::Entry* entry = tokens_map_.Lookup( | |
318 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false); | |
319 if (entry != NULL) { | |
320 intptr_t tokens = reinterpret_cast<intptr_t>(entry->value); | |
321 if (tokens == 0) { | |
322 while (idle_ports_.head() != port) { | |
323 idle_ports_.Rotate(); | |
324 } | |
325 idle_ports_.RemoveHead(); | |
326 } else { | |
327 while (live_ports_.head() != port) { | |
328 live_ports_.Rotate(); | |
329 } | |
330 live_ports_.RemoveHead(); | |
331 } | |
332 tokens_map_.Remove( | |
333 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port)); | |
334 } else { | |
335 // NOTE: This is a listening socket which has been immediately closed. | |
336 // | |
337 // If a listening socket is not listened on, the event handler does not | |
338 // know about it beforehand. So the first time the event handler knows | |
339 // about it, is when it is supposed to be closed. We therefore do nothing | |
340 // here. | |
341 // | |
342 // But whether to close it, depends on whether other isolates have it open | |
343 // as well or not. | |
344 } | |
345 return !live_ports_.HasHead(); | |
346 } | |
347 | |
348 virtual Dart_Port NextPort() { | |
349 ASSERT(live_ports_.HasHead()); | |
350 return live_ports_.head(); | |
351 } | |
352 | |
353 virtual bool HasNextPort() { | |
354 return live_ports_.HasHead(); | |
355 } | |
356 | |
357 virtual bool TakeToken() { | |
358 ASSERT(live_ports_.HasHead()); | |
359 Dart_Port port = live_ports_.head(); | |
360 HashMap::Entry* entry = tokens_map_.Lookup( | |
361 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false); | |
362 ASSERT(entry != NULL); | |
363 intptr_t tokens = reinterpret_cast<intptr_t>(entry->value); | |
364 tokens--; | |
365 entry->value = reinterpret_cast<void*>(tokens); | |
366 if (tokens == 0) { | |
367 live_ports_.RemoveHead(); | |
368 idle_ports_.Add(port); | |
369 if (!live_ports_.HasHead()) { | |
370 return true; | |
371 } | |
372 } else { | |
373 live_ports_.Rotate(); | |
374 } | |
375 return false; | |
376 } | |
377 | |
378 virtual bool ReturnTokens(Dart_Port port, int count) { | |
379 HashMap::Entry* entry = tokens_map_.Lookup( | |
380 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false); | |
381 ASSERT(entry != NULL); | |
382 intptr_t tokens = reinterpret_cast<intptr_t>(entry->value); | |
383 tokens += count; | |
384 entry->value = reinterpret_cast<void*>(tokens); | |
385 if (tokens == count) { | |
386 // Return to live_ports_. | |
387 while (idle_ports_.head() != port) { | |
388 idle_ports_.Rotate(); | |
389 } | |
390 idle_ports_.RemoveHead(); | |
391 bool was_empty = !live_ports_.HasHead(); | |
392 live_ports_.Add(port); | |
393 return was_empty; | |
394 } | |
395 return false; | |
396 } | |
397 | |
398 virtual bool HasTokens() const { | |
399 return live_ports_.HasHead(); | |
400 } | |
401 | |
402 virtual void Close() { | |
403 SI::Close(); | |
404 } | |
405 | |
406 private: | |
407 CircularLinkedList<Dart_Port> live_ports_; | |
408 CircularLinkedList<Dart_Port> idle_ports_; | |
409 HashMap tokens_map_; | |
410 }; | |
411 | |
412 | |
413 class InterruptMessage { | |
414 public: | |
415 intptr_t id; | |
416 Dart_Port dart_port; | |
417 int64_t data; | |
418 }; | |
419 | |
420 | |
421 static const int kInterruptMessageSize = sizeof(InterruptMessage); | |
422 static const int kInfinityTimeout = -1; | |
423 static const int kTimerId = -1; | |
424 static const int kShutdownId = -2; | |
425 | |
97 } // namespace bin | 426 } // namespace bin |
98 } // namespace dart | 427 } // namespace dart |
99 | 428 |
100 // The event handler delegation class is OS specific. | 429 // The event handler delegation class is OS specific. |
101 #if defined(TARGET_OS_ANDROID) | 430 #if defined(TARGET_OS_ANDROID) |
102 #include "bin/eventhandler_android.h" | 431 #include "bin/eventhandler_android.h" |
103 #elif defined(TARGET_OS_LINUX) | 432 #elif defined(TARGET_OS_LINUX) |
104 #include "bin/eventhandler_linux.h" | 433 #include "bin/eventhandler_linux.h" |
105 #elif defined(TARGET_OS_MACOS) | 434 #elif defined(TARGET_OS_MACOS) |
106 #include "bin/eventhandler_macos.h" | 435 #include "bin/eventhandler_macos.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
134 | 463 |
135 private: | 464 private: |
136 friend class EventHandlerImplementation; | 465 friend class EventHandlerImplementation; |
137 EventHandlerImplementation delegate_; | 466 EventHandlerImplementation delegate_; |
138 }; | 467 }; |
139 | 468 |
140 } // namespace bin | 469 } // namespace bin |
141 } // namespace dart | 470 } // namespace dart |
142 | 471 |
143 #endif // BIN_EVENTHANDLER_H_ | 472 #endif // BIN_EVENTHANDLER_H_ |
OLD | NEW |