| 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/dartutils.h" | 9 #include "bin/dartutils.h" |
| 10 #include "bin/isolate_data.h" | 10 #include "bin/isolate_data.h" |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 prev->next_ = next; | 179 prev->next_ = next; |
| 180 next->prev_ = prev; | 180 next->prev_ = prev; |
| 181 delete current; | 181 delete current; |
| 182 return; | 182 return; |
| 183 } | 183 } |
| 184 current = current->next_; | 184 current = current->next_; |
| 185 } while (current != head_); | 185 } while (current != head_); |
| 186 } | 186 } |
| 187 } | 187 } |
| 188 | 188 |
| 189 void RemoveAll() { |
| 190 while (HasHead()) { |
| 191 RemoveHead(); |
| 192 } |
| 193 } |
| 189 | 194 |
| 190 T head() const { return head_->t; } | 195 T head() const { return head_->t; } |
| 191 | 196 |
| 192 bool HasHead() const { | 197 bool HasHead() const { |
| 193 return head_ != NULL; | 198 return head_ != NULL; |
| 194 } | 199 } |
| 195 | 200 |
| 196 void Rotate() { | 201 void Rotate() { |
| 197 if (head_ != NULL) { | 202 if (head_ != NULL) { |
| 198 ASSERT(head_->next_ != NULL); | 203 ASSERT(head_->next_ != NULL); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 226 // Whether this descriptor refers to an underlying listening OS socket. | 231 // Whether this descriptor refers to an underlying listening OS socket. |
| 227 virtual bool IsListeningSocket() const = 0; | 232 virtual bool IsListeningSocket() const = 0; |
| 228 | 233 |
| 229 // Inserts or updates a new Dart_Port which is interested in events specified | 234 // Inserts or updates a new Dart_Port which is interested in events specified |
| 230 // in `mask`. | 235 // in `mask`. |
| 231 virtual void SetPortAndMask(Dart_Port port, intptr_t mask) = 0; | 236 virtual void SetPortAndMask(Dart_Port port, intptr_t mask) = 0; |
| 232 | 237 |
| 233 // Removes a port from the interested listeners. | 238 // Removes a port from the interested listeners. |
| 234 virtual void RemovePort(Dart_Port port) = 0; | 239 virtual void RemovePort(Dart_Port port) = 0; |
| 235 | 240 |
| 241 // Removes all ports from the interested listeners. |
| 242 virtual void RemoveAllPorts() = 0; |
| 243 |
| 236 // Returns a port to which `events_ready` can be sent to. It will also | 244 // Returns a port to which `events_ready` can be sent to. It will also |
| 237 // decrease the token count by 1 for this port. | 245 // decrease the token count by 1 for this port. |
| 238 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) = 0; | 246 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) = 0; |
| 239 | 247 |
| 240 // Will post `data` to all known Dart_Ports. It will also decrease the token | 248 // Will post `data` to all known Dart_Ports. It will also decrease the token |
| 241 // count by 1 for all ports. | 249 // count by 1 for all ports. |
| 242 virtual void NotifyAllDartPorts(uintptr_t events) = 0; | 250 virtual void NotifyAllDartPorts(uintptr_t events) = 0; |
| 243 | 251 |
| 244 // Returns `count` tokens for the given port. | 252 // Returns `count` tokens for the given port. |
| 245 virtual void ReturnTokens(Dart_Port port, int count) = 0; | 253 virtual void ReturnTokens(Dart_Port port, int count) = 0; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 259 // Describes a OS descriptor (e.g. file descriptor on linux or HANDLE on | 267 // Describes a OS descriptor (e.g. file descriptor on linux or HANDLE on |
| 260 // windows) which is connected to a single Dart_Port. | 268 // windows) which is connected to a single Dart_Port. |
| 261 // | 269 // |
| 262 // Subclasses of this class can be e.g. connected tcp sockets. | 270 // Subclasses of this class can be e.g. connected tcp sockets. |
| 263 template<typename DI> | 271 template<typename DI> |
| 264 class DescriptorInfoSingleMixin : public DI { | 272 class DescriptorInfoSingleMixin : public DI { |
| 265 private: | 273 private: |
| 266 static const int kTokenCount = 16; | 274 static const int kTokenCount = 16; |
| 267 | 275 |
| 268 public: | 276 public: |
| 269 explicit DescriptorInfoSingleMixin(intptr_t fd) | 277 explicit DescriptorInfoSingleMixin(intptr_t fd, bool disable_tokens) |
| 270 : DI(fd), port_(0), tokens_(kTokenCount), mask_(0) {} | 278 : DI(fd), port_(0), tokens_(kTokenCount), mask_(0), |
| 279 disable_tokens_(disable_tokens) {} |
| 271 | 280 |
| 272 virtual ~DescriptorInfoSingleMixin() { } | 281 virtual ~DescriptorInfoSingleMixin() { } |
| 273 | 282 |
| 274 virtual bool IsListeningSocket() const { return false; } | 283 virtual bool IsListeningSocket() const { return false; } |
| 275 | 284 |
| 276 virtual void SetPortAndMask(Dart_Port port, intptr_t mask) { | 285 virtual void SetPortAndMask(Dart_Port port, intptr_t mask) { |
| 277 ASSERT(port_ == 0 || port == port_); | 286 ASSERT(port_ == 0 || port == port_); |
| 278 port_ = port; | 287 port_ = port; |
| 279 mask_ = mask; | 288 mask_ = mask; |
| 280 } | 289 } |
| 281 | 290 |
| 282 virtual void RemovePort(Dart_Port port) { | 291 virtual void RemovePort(Dart_Port port) { |
| 283 // TODO(dart:io): Find out where we call RemovePort() with the invalid | 292 // TODO(dart:io): Find out where we call RemovePort() with the invalid |
| 284 // port. Afterwards remove the part in the ASSERT here. | 293 // port. Afterwards remove the part in the ASSERT here. |
| 285 ASSERT(port_ == 0 || port_ == port); | 294 ASSERT(port_ == 0 || port_ == port); |
| 286 port_ = 0; | 295 port_ = 0; |
| 287 mask_ = 0; | 296 mask_ = 0; |
| 288 } | 297 } |
| 289 | 298 |
| 299 virtual void RemoveAllPorts() { |
| 300 port_ = 0; |
| 301 mask_ = 0; |
| 302 } |
| 303 |
| 290 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) { | 304 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) { |
| 291 ASSERT(IS_IO_EVENT(events_ready) || | 305 ASSERT(IS_IO_EVENT(events_ready) || |
| 292 IS_EVENT(events_ready, kDestroyedEvent)); | 306 IS_EVENT(events_ready, kDestroyedEvent)); |
| 293 tokens_--; | 307 if (!disable_tokens_) { |
| 308 tokens_--; |
| 309 } |
| 294 return port_; | 310 return port_; |
| 295 } | 311 } |
| 296 | 312 |
| 297 virtual void NotifyAllDartPorts(uintptr_t events) { | 313 virtual void NotifyAllDartPorts(uintptr_t events) { |
| 298 // Unexpected close or error events are the only ones we broadcast to all | 314 // Unexpected close, asynchronous destroy or error events are the only |
| 299 // listeners and are the only ones where we do not count tokens. | 315 // ones we broadcast to all listeners. |
| 300 ASSERT(IS_EVENT(events, kCloseEvent) || | 316 ASSERT(IS_EVENT(events, kCloseEvent) || |
| 301 IS_EVENT(events, kErrorEvent)); | 317 IS_EVENT(events, kErrorEvent) || |
| 318 IS_EVENT(events, kDestroyedEvent)); |
| 302 | 319 |
| 303 if (port_ != 0) { | 320 if (port_ != 0) { |
| 304 DartUtils::PostInt32(port_, events); | 321 DartUtils::PostInt32(port_, events); |
| 305 } | 322 } |
| 306 tokens_--; | 323 if (!disable_tokens_) { |
| 324 tokens_--; |
| 325 } |
| 307 } | 326 } |
| 308 | 327 |
| 309 virtual void ReturnTokens(Dart_Port port, int count) { | 328 virtual void ReturnTokens(Dart_Port port, int count) { |
| 310 ASSERT(port_ == port); | 329 ASSERT(port_ == port); |
| 311 ASSERT(tokens_ >= 0); | 330 ASSERT(tokens_ >= 0); |
| 312 tokens_ += count; | 331 if (!disable_tokens_) { |
| 332 tokens_ += count; |
| 333 } |
| 313 ASSERT(tokens_ <= kTokenCount); | 334 ASSERT(tokens_ <= kTokenCount); |
| 314 } | 335 } |
| 315 | 336 |
| 316 virtual intptr_t Mask() { | 337 virtual intptr_t Mask() { |
| 317 if (tokens_ <= 0) { | 338 if (tokens_ <= 0) { |
| 318 return 0; | 339 return 0; |
| 319 } | 340 } |
| 320 return mask_; | 341 return mask_; |
| 321 } | 342 } |
| 322 | 343 |
| 323 virtual void Close() { | 344 virtual void Close() { |
| 324 DI::Close(); | 345 DI::Close(); |
| 325 } | 346 } |
| 326 | 347 |
| 327 private: | 348 private: |
| 328 Dart_Port port_; | 349 Dart_Port port_; |
| 329 int tokens_; | 350 int tokens_; |
| 330 intptr_t mask_; | 351 intptr_t mask_; |
| 352 bool disable_tokens_; |
| 331 }; | 353 }; |
| 332 | 354 |
| 333 | 355 |
| 334 // Describes a OS descriptor (e.g. file descriptor on linux or HANDLE on | 356 // Describes a OS descriptor (e.g. file descriptor on linux or HANDLE on |
| 335 // windows) which is connected to multiple Dart_Port's. | 357 // windows) which is connected to multiple Dart_Port's. |
| 336 // | 358 // |
| 337 // Subclasses of this class can be e.g. a listening socket which multiple | 359 // Subclasses of this class can be e.g. a listening socket which multiple |
| 338 // isolates are listening on. | 360 // isolates are listening on. |
| 339 template<typename DI> | 361 template<typename DI> |
| 340 class DescriptorInfoMultipleMixin : public DI { | 362 class DescriptorInfoMultipleMixin : public DI { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 365 | 387 |
| 366 struct PortEntry { | 388 struct PortEntry { |
| 367 Dart_Port dart_port; | 389 Dart_Port dart_port; |
| 368 intptr_t is_reading; | 390 intptr_t is_reading; |
| 369 intptr_t token_count; | 391 intptr_t token_count; |
| 370 | 392 |
| 371 bool IsReady() { return token_count > 0 && is_reading; } | 393 bool IsReady() { return token_count > 0 && is_reading; } |
| 372 }; | 394 }; |
| 373 | 395 |
| 374 public: | 396 public: |
| 375 explicit DescriptorInfoMultipleMixin(intptr_t fd) | 397 explicit DescriptorInfoMultipleMixin(intptr_t fd, bool disable_tokens) |
| 376 : DI(fd), tokens_map_(&SamePortValue, kTokenCount) {} | 398 : DI(fd), tokens_map_(&SamePortValue, kTokenCount), |
| 399 disable_tokens_(disable_tokens) {} |
| 377 | 400 |
| 378 virtual ~DescriptorInfoMultipleMixin() {} | 401 virtual ~DescriptorInfoMultipleMixin() {} |
| 379 | 402 |
| 380 virtual bool IsListeningSocket() const { return true; } | 403 virtual bool IsListeningSocket() const { return true; } |
| 381 | 404 |
| 382 virtual void SetPortAndMask(Dart_Port port, intptr_t mask) { | 405 virtual void SetPortAndMask(Dart_Port port, intptr_t mask) { |
| 383 HashMap::Entry* entry = tokens_map_.Lookup( | 406 HashMap::Entry* entry = tokens_map_.Lookup( |
| 384 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), true); | 407 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), true); |
| 385 PortEntry* pentry; | 408 PortEntry* pentry; |
| 386 if (entry->value == NULL) { | 409 if (entry->value == NULL) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 401 | 424 |
| 402 if (was_ready && !is_ready) { | 425 if (was_ready && !is_ready) { |
| 403 active_readers_.Remove(pentry); | 426 active_readers_.Remove(pentry); |
| 404 } else if (!was_ready && is_ready) { | 427 } else if (!was_ready && is_ready) { |
| 405 active_readers_.Add(pentry); | 428 active_readers_.Add(pentry); |
| 406 } | 429 } |
| 407 } | 430 } |
| 408 | 431 |
| 409 #ifdef DEBUG | 432 #ifdef DEBUG |
| 410 // To ensure that all readers are ready. | 433 // To ensure that all readers are ready. |
| 411 PortEntry* root = reinterpret_cast<PortEntry*>(active_readers_.head()); | 434 int ready_count = 0; |
| 412 | 435 |
| 413 int ready_count = 0; | 436 if (active_readers_.HasHead()) { |
| 414 if (root != NULL) { | 437 PortEntry* root = reinterpret_cast<PortEntry*>(active_readers_.head()); |
| 415 PortEntry* current = root; | 438 PortEntry* current = root; |
| 416 do { | 439 do { |
| 417 ASSERT(current->IsReady()); | 440 ASSERT(current->IsReady()); |
| 418 ready_count++; | 441 ready_count++; |
| 419 active_readers_.Rotate(); | 442 active_readers_.Rotate(); |
| 420 current = active_readers_.head(); | 443 current = active_readers_.head(); |
| 421 } while (current != root); | 444 } while (current != root); |
| 422 } | 445 } |
| 446 |
| 423 for (HashMap::Entry *entry = tokens_map_.Start(); | 447 for (HashMap::Entry *entry = tokens_map_.Start(); |
| 424 entry != NULL; | 448 entry != NULL; |
| 425 entry = tokens_map_.Next(entry)) { | 449 entry = tokens_map_.Next(entry)) { |
| 426 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value); | 450 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value); |
| 427 if (pentry->IsReady()) { | 451 if (pentry->IsReady()) { |
| 428 ready_count--; | 452 ready_count--; |
| 429 } | 453 } |
| 430 } | 454 } |
| 431 // Ensure all ready items are in `active_readers_`. | 455 // Ensure all ready items are in `active_readers_`. |
| 432 ASSERT(ready_count == 0); | 456 ASSERT(ready_count == 0); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 450 // If a listening socket is not listened on, the event handler does not | 474 // If a listening socket is not listened on, the event handler does not |
| 451 // know about it beforehand. So the first time the event handler knows | 475 // know about it beforehand. So the first time the event handler knows |
| 452 // about it, is when it is supposed to be closed. We therefore do nothing | 476 // about it, is when it is supposed to be closed. We therefore do nothing |
| 453 // here. | 477 // here. |
| 454 // | 478 // |
| 455 // But whether to close it, depends on whether other isolates have it open | 479 // But whether to close it, depends on whether other isolates have it open |
| 456 // as well or not. | 480 // as well or not. |
| 457 } | 481 } |
| 458 } | 482 } |
| 459 | 483 |
| 484 virtual void RemoveAllPorts() { |
| 485 active_readers_.RemoveAll(); |
| 486 for (HashMap::Entry *entry = tokens_map_.Start(); |
| 487 entry != NULL; |
| 488 entry = tokens_map_.Next(entry)) { |
| 489 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value); |
| 490 delete pentry; |
| 491 } |
| 492 tokens_map_.Clear(); |
| 493 } |
| 494 |
| 460 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) { | 495 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) { |
| 461 // We're only sending `kInEvents` if there are multiple listeners (which is | 496 // We're only sending `kInEvents` if there are multiple listeners (which is |
| 462 // listening socktes). | 497 // listening socktes). |
| 463 ASSERT(IS_EVENT(events_ready, kInEvent) || | 498 ASSERT(IS_EVENT(events_ready, kInEvent) || |
| 464 IS_EVENT(events_ready, kDestroyedEvent)); | 499 IS_EVENT(events_ready, kDestroyedEvent)); |
| 465 | 500 |
| 466 if (active_readers_.HasHead()) { | 501 if (active_readers_.HasHead()) { |
| 467 PortEntry* pentry = reinterpret_cast<PortEntry*>(active_readers_.head()); | 502 PortEntry* pentry = reinterpret_cast<PortEntry*>(active_readers_.head()); |
| 468 | 503 |
| 469 // Update token count. | 504 // Update token count. |
| 470 pentry->token_count--; | 505 if (!disable_tokens_) { |
| 506 pentry->token_count--; |
| 507 } |
| 471 if (pentry->token_count <= 0) { | 508 if (pentry->token_count <= 0) { |
| 472 active_readers_.RemoveHead(); | 509 active_readers_.RemoveHead(); |
| 473 } else { | 510 } else { |
| 474 active_readers_.Rotate(); | 511 active_readers_.Rotate(); |
| 475 } | 512 } |
| 476 | 513 |
| 477 return pentry->dart_port; | 514 return pentry->dart_port; |
| 478 } | 515 } |
| 479 return 0; | 516 return 0; |
| 480 } | 517 } |
| 481 | 518 |
| 482 virtual void NotifyAllDartPorts(uintptr_t events) { | 519 virtual void NotifyAllDartPorts(uintptr_t events) { |
| 483 // Unexpected close or error events are the only ones we broadcast to all | 520 // Unexpected close, asynchronous destroy or error events are the only |
| 484 // listeners and are the only ones where we do not count tokens. | 521 // ones we broadcast to all listeners. |
| 485 ASSERT(IS_EVENT(events, kCloseEvent) || | 522 ASSERT(IS_EVENT(events, kCloseEvent) || |
| 486 IS_EVENT(events, kErrorEvent)); | 523 IS_EVENT(events, kErrorEvent) || |
| 524 IS_EVENT(events, kDestroyedEvent)); |
| 487 | 525 |
| 488 for (HashMap::Entry *entry = tokens_map_.Start(); | 526 for (HashMap::Entry *entry = tokens_map_.Start(); |
| 489 entry != NULL; | 527 entry != NULL; |
| 490 entry = tokens_map_.Next(entry)) { | 528 entry = tokens_map_.Next(entry)) { |
| 491 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value); | 529 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value); |
| 492 DartUtils::PostInt32(pentry->dart_port, events); | 530 DartUtils::PostInt32(pentry->dart_port, events); |
| 493 | 531 |
| 494 // Update token count. | 532 // Update token count. |
| 495 bool was_ready = pentry->IsReady(); | 533 bool was_ready = pentry->IsReady(); |
| 496 pentry->token_count--; | 534 if (!disable_tokens_) { |
| 535 pentry->token_count--; |
| 536 } |
| 497 | 537 |
| 498 if (was_ready && pentry->token_count <= 0) { | 538 if (was_ready && pentry->token_count <= 0) { |
| 499 active_readers_.Remove(pentry); | 539 active_readers_.Remove(pentry); |
| 500 } | 540 } |
| 501 } | 541 } |
| 502 } | 542 } |
| 503 | 543 |
| 504 virtual void ReturnTokens(Dart_Port port, int count) { | 544 virtual void ReturnTokens(Dart_Port port, int count) { |
| 505 HashMap::Entry* entry = tokens_map_.Lookup( | 545 HashMap::Entry* entry = tokens_map_.Lookup( |
| 506 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false); | 546 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false); |
| 507 ASSERT(entry != NULL); | 547 ASSERT(entry != NULL); |
| 508 | 548 |
| 509 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value); | 549 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value); |
| 510 bool was_ready = pentry->IsReady(); | 550 bool was_ready = pentry->IsReady(); |
| 511 ASSERT(pentry->token_count >= 0); | 551 ASSERT(pentry->token_count >= 0); |
| 512 pentry->token_count += count; | 552 if (!disable_tokens_) { |
| 553 pentry->token_count += count; |
| 554 } |
| 513 ASSERT(pentry->token_count <= kTokenCount); | 555 ASSERT(pentry->token_count <= kTokenCount); |
| 514 bool is_ready = pentry->token_count > 0 && pentry->IsReady(); | 556 bool is_ready = pentry->token_count > 0 && pentry->IsReady(); |
| 515 if (!was_ready && is_ready) { | 557 if (!was_ready && is_ready) { |
| 516 active_readers_.Add(pentry); | 558 active_readers_.Add(pentry); |
| 517 } | 559 } |
| 518 } | 560 } |
| 519 | 561 |
| 520 virtual intptr_t Mask() { | 562 virtual intptr_t Mask() { |
| 521 if (active_readers_.HasHead()) { | 563 if (active_readers_.HasHead()) { |
| 522 return 1 << kInEvent; | 564 return 1 << kInEvent; |
| 523 } | 565 } |
| 524 return 0; | 566 return 0; |
| 525 } | 567 } |
| 526 | 568 |
| 527 virtual void Close() { | 569 virtual void Close() { |
| 528 DI::Close(); | 570 DI::Close(); |
| 529 } | 571 } |
| 530 | 572 |
| 531 private: | 573 private: |
| 532 // The [Dart_Port]s which are not paused (i.e. are interested in read events, | 574 // The [Dart_Port]s which are not paused (i.e. are interested in read events, |
| 533 // i.e. `mask == (1 << kInEvent)`) and we have enough tokens to communicate | 575 // i.e. `mask == (1 << kInEvent)`) and we have enough tokens to communicate |
| 534 // with them. | 576 // with them. |
| 535 CircularLinkedList<PortEntry *> active_readers_; | 577 CircularLinkedList<PortEntry *> active_readers_; |
| 536 | 578 |
| 537 // A convenience mapping: | 579 // A convenience mapping: |
| 538 // Dart_Port -> struct PortEntry { dart_port, mask, token_count } | 580 // Dart_Port -> struct PortEntry { dart_port, mask, token_count } |
| 539 HashMap tokens_map_; | 581 HashMap tokens_map_; |
| 582 |
| 583 bool disable_tokens_; |
| 540 }; | 584 }; |
| 541 | 585 |
| 542 | 586 |
| 543 } // namespace bin | 587 } // namespace bin |
| 544 } // namespace dart | 588 } // namespace dart |
| 545 | 589 |
| 546 // The event handler delegation class is OS specific. | 590 // The event handler delegation class is OS specific. |
| 547 #if defined(TARGET_OS_ANDROID) | 591 #if defined(TARGET_OS_ANDROID) |
| 548 #include "bin/eventhandler_android.h" | 592 #include "bin/eventhandler_android.h" |
| 549 #elif defined(TARGET_OS_LINUX) | 593 #elif defined(TARGET_OS_LINUX) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 | 629 |
| 586 private: | 630 private: |
| 587 friend class EventHandlerImplementation; | 631 friend class EventHandlerImplementation; |
| 588 EventHandlerImplementation delegate_; | 632 EventHandlerImplementation delegate_; |
| 589 }; | 633 }; |
| 590 | 634 |
| 591 } // namespace bin | 635 } // namespace bin |
| 592 } // namespace dart | 636 } // namespace dart |
| 593 | 637 |
| 594 #endif // BIN_EVENTHANDLER_H_ | 638 #endif // BIN_EVENTHANDLER_H_ |
| OLD | NEW |