OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/public/cpp/bindings/lib/multiplex_router.h" | 5 #include "mojo/public/cpp/bindings/lib/multiplex_router.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 } | 420 } |
421 | 421 |
422 InterfaceId MultiplexRouter::AssociateInterface( | 422 InterfaceId MultiplexRouter::AssociateInterface( |
423 ScopedInterfaceEndpointHandle handle_to_send) { | 423 ScopedInterfaceEndpointHandle handle_to_send) { |
424 if (!handle_to_send.pending_association()) | 424 if (!handle_to_send.pending_association()) |
425 return kInvalidInterfaceId; | 425 return kInvalidInterfaceId; |
426 | 426 |
427 uint32_t id = 0; | 427 uint32_t id = 0; |
428 { | 428 { |
429 MayAutoLock locker(lock_.get()); | 429 MayAutoLock locker(lock_.get()); |
| 430 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 431 // The lock above protects |endpoint|. |
| 432 base::ScopedAllowCrossThreadRefCountAccess |
| 433 allow_cross_thread_ref_count_access; |
430 do { | 434 do { |
431 if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) | 435 if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) |
432 next_interface_id_value_ = 1; | 436 next_interface_id_value_ = 1; |
433 id = next_interface_id_value_++; | 437 id = next_interface_id_value_++; |
434 if (set_interface_id_namespace_bit_) | 438 if (set_interface_id_namespace_bit_) |
435 id |= kInterfaceIdNamespaceMask; | 439 id |= kInterfaceIdNamespaceMask; |
436 } while (base::ContainsKey(endpoints_, id)); | 440 } while (base::ContainsKey(endpoints_, id)); |
437 | 441 |
438 InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); | 442 InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); |
439 endpoints_[id] = endpoint; | 443 endpoints_[id] = endpoint; |
(...skipping 17 matching lines...) Expand all Loading... |
457 } | 461 } |
458 return id; | 462 return id; |
459 } | 463 } |
460 | 464 |
461 ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( | 465 ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( |
462 InterfaceId id) { | 466 InterfaceId id) { |
463 if (!IsValidInterfaceId(id)) | 467 if (!IsValidInterfaceId(id)) |
464 return ScopedInterfaceEndpointHandle(); | 468 return ScopedInterfaceEndpointHandle(); |
465 | 469 |
466 MayAutoLock locker(lock_.get()); | 470 MayAutoLock locker(lock_.get()); |
| 471 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 472 // The lock above protects |endpoint|. |
| 473 base::ScopedAllowCrossThreadRefCountAccess |
| 474 allow_cross_thread_ref_count_access; |
467 bool inserted = false; | 475 bool inserted = false; |
468 InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); | 476 InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); |
469 if (inserted) { | 477 if (inserted) { |
470 DCHECK(!endpoint->handle_created()); | 478 DCHECK(!endpoint->handle_created()); |
471 | 479 |
472 if (encountered_error_) | 480 if (encountered_error_) |
473 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); | 481 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); |
474 } else { | 482 } else { |
475 // If the endpoint already exist, it is because we have received a | 483 // If the endpoint already exist, it is because we have received a |
476 // notification that the peer endpoint has closed. | 484 // notification that the peer endpoint has closed. |
477 CHECK(!endpoint->closed()); | 485 CHECK(!endpoint->closed()); |
478 CHECK(endpoint->peer_closed()); | 486 CHECK(endpoint->peer_closed()); |
479 | 487 |
480 if (endpoint->handle_created()) | 488 if (endpoint->handle_created()) |
481 return ScopedInterfaceEndpointHandle(); | 489 return ScopedInterfaceEndpointHandle(); |
482 } | 490 } |
483 | 491 |
484 endpoint->set_handle_created(); | 492 endpoint->set_handle_created(); |
485 return CreateScopedInterfaceEndpointHandle(id); | 493 return CreateScopedInterfaceEndpointHandle(id); |
486 } | 494 } |
487 | 495 |
488 void MultiplexRouter::CloseEndpointHandle( | 496 void MultiplexRouter::CloseEndpointHandle( |
489 InterfaceId id, | 497 InterfaceId id, |
490 const base::Optional<DisconnectReason>& reason) { | 498 const base::Optional<DisconnectReason>& reason) { |
491 if (!IsValidInterfaceId(id)) | 499 if (!IsValidInterfaceId(id)) |
492 return; | 500 return; |
493 | 501 |
494 MayAutoLock locker(lock_.get()); | 502 MayAutoLock locker(lock_.get()); |
| 503 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 504 // The lock above protects |endpoint|. |
| 505 base::ScopedAllowCrossThreadRefCountAccess |
| 506 allow_cross_thread_ref_count_access; |
495 DCHECK(base::ContainsKey(endpoints_, id)); | 507 DCHECK(base::ContainsKey(endpoints_, id)); |
496 InterfaceEndpoint* endpoint = endpoints_[id].get(); | 508 InterfaceEndpoint* endpoint = endpoints_[id].get(); |
497 DCHECK(!endpoint->client()); | 509 DCHECK(!endpoint->client()); |
498 DCHECK(!endpoint->closed()); | 510 DCHECK(!endpoint->closed()); |
499 UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); | 511 UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); |
500 | 512 |
501 if (!IsMasterInterfaceId(id) || reason) { | 513 if (!IsMasterInterfaceId(id) || reason) { |
502 MayAutoUnlock unlocker(lock_.get()); | 514 MayAutoUnlock unlocker(lock_.get()); |
503 control_message_proxy_.NotifyPeerEndpointClosed(id, reason); | 515 control_message_proxy_.NotifyPeerEndpointClosed(id, reason); |
504 } | 516 } |
505 | 517 |
506 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); | 518 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); |
507 } | 519 } |
508 | 520 |
509 InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( | 521 InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( |
510 const ScopedInterfaceEndpointHandle& handle, | 522 const ScopedInterfaceEndpointHandle& handle, |
511 InterfaceEndpointClient* client, | 523 InterfaceEndpointClient* client, |
512 scoped_refptr<base::SingleThreadTaskRunner> runner) { | 524 scoped_refptr<base::SingleThreadTaskRunner> runner) { |
513 const InterfaceId id = handle.id(); | 525 const InterfaceId id = handle.id(); |
514 | 526 |
515 DCHECK(IsValidInterfaceId(id)); | 527 DCHECK(IsValidInterfaceId(id)); |
516 DCHECK(client); | 528 DCHECK(client); |
517 | 529 |
518 MayAutoLock locker(lock_.get()); | 530 MayAutoLock locker(lock_.get()); |
| 531 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 532 // The lock above protects |endpoint|. |
| 533 base::ScopedAllowCrossThreadRefCountAccess |
| 534 allow_cross_thread_ref_count_access; |
519 DCHECK(base::ContainsKey(endpoints_, id)); | 535 DCHECK(base::ContainsKey(endpoints_, id)); |
520 | 536 |
521 InterfaceEndpoint* endpoint = endpoints_[id].get(); | 537 InterfaceEndpoint* endpoint = endpoints_[id].get(); |
522 endpoint->AttachClient(client, std::move(runner)); | 538 endpoint->AttachClient(client, std::move(runner)); |
523 | 539 |
524 if (endpoint->peer_closed()) | 540 if (endpoint->peer_closed()) |
525 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); | 541 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); |
526 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); | 542 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); |
527 | 543 |
528 return endpoint; | 544 return endpoint; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 // No need to trigger a ProcessTasks() because it is already on the stack. | 694 // No need to trigger a ProcessTasks() because it is already on the stack. |
679 | 695 |
680 return true; | 696 return true; |
681 } | 697 } |
682 | 698 |
683 void MultiplexRouter::OnPipeConnectionError() { | 699 void MultiplexRouter::OnPipeConnectionError() { |
684 DCHECK(thread_checker_.CalledOnValidThread()); | 700 DCHECK(thread_checker_.CalledOnValidThread()); |
685 | 701 |
686 scoped_refptr<MultiplexRouter> protector(this); | 702 scoped_refptr<MultiplexRouter> protector(this); |
687 MayAutoLock locker(lock_.get()); | 703 MayAutoLock locker(lock_.get()); |
| 704 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 705 // The lock above protects |endpoint|. |
| 706 base::ScopedAllowCrossThreadRefCountAccess |
| 707 allow_cross_thread_ref_count_access; |
688 | 708 |
689 encountered_error_ = true; | 709 encountered_error_ = true; |
690 | 710 |
691 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { | 711 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { |
692 InterfaceEndpoint* endpoint = iter->second.get(); | 712 InterfaceEndpoint* endpoint = iter->second.get(); |
693 // Increment the iterator before calling UpdateEndpointStateMayRemove() | 713 // Increment the iterator before calling UpdateEndpointStateMayRemove() |
694 // because it may remove the corresponding value from the map. | 714 // because it may remove the corresponding value from the map. |
695 ++iter; | 715 ++iter; |
696 | 716 |
697 if (endpoint->client()) | 717 if (endpoint->client()) |
698 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); | 718 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); |
699 | 719 |
700 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); | 720 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); |
701 } | 721 } |
702 | 722 |
703 ProcessTasks(connector_.during_sync_handle_watcher_callback() | 723 ProcessTasks(connector_.during_sync_handle_watcher_callback() |
704 ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES | 724 ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES |
705 : ALLOW_DIRECT_CLIENT_CALLS, | 725 : ALLOW_DIRECT_CLIENT_CALLS, |
706 connector_.task_runner()); | 726 connector_.task_runner()); |
707 } | 727 } |
708 | 728 |
709 void MultiplexRouter::ProcessTasks( | 729 void MultiplexRouter::ProcessTasks( |
710 ClientCallBehavior client_call_behavior, | 730 ClientCallBehavior client_call_behavior, |
711 base::SingleThreadTaskRunner* current_task_runner) { | 731 base::SingleThreadTaskRunner* current_task_runner) { |
712 AssertLockAcquired(); | 732 AssertLockAcquired(); |
| 733 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 734 // The lock above protects |endpoint|. |
| 735 base::ScopedAllowCrossThreadRefCountAccess |
| 736 allow_cross_thread_ref_count_access; |
713 | 737 |
714 if (posted_to_process_tasks_) | 738 if (posted_to_process_tasks_) |
715 return; | 739 return; |
716 | 740 |
717 while (!tasks_.empty() && !paused_) { | 741 while (!tasks_.empty() && !paused_) { |
718 std::unique_ptr<Task> task(std::move(tasks_.front())); | 742 std::unique_ptr<Task> task(std::move(tasks_.front())); |
719 tasks_.pop_front(); | 743 tasks_.pop_front(); |
720 | 744 |
721 InterfaceId id = kInvalidInterfaceId; | 745 InterfaceId id = kInvalidInterfaceId; |
722 bool sync_message = | 746 bool sync_message = |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 | 997 |
974 void MultiplexRouter::AssertLockAcquired() { | 998 void MultiplexRouter::AssertLockAcquired() { |
975 #if DCHECK_IS_ON() | 999 #if DCHECK_IS_ON() |
976 if (lock_) | 1000 if (lock_) |
977 lock_->AssertAcquired(); | 1001 lock_->AssertAcquired(); |
978 #endif | 1002 #endif |
979 } | 1003 } |
980 | 1004 |
981 } // namespace internal | 1005 } // namespace internal |
982 } // namespace mojo | 1006 } // namespace mojo |
OLD | NEW |