Chromium Code Reviews| 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 |