Chromium Code Reviews| 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 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 } | 424 } |
| 425 | 425 |
| 426 InterfaceId MultiplexRouter::AssociateInterface( | 426 InterfaceId MultiplexRouter::AssociateInterface( |
| 427 ScopedInterfaceEndpointHandle handle_to_send) { | 427 ScopedInterfaceEndpointHandle handle_to_send) { |
| 428 if (!handle_to_send.pending_association()) | 428 if (!handle_to_send.pending_association()) |
| 429 return kInvalidInterfaceId; | 429 return kInvalidInterfaceId; |
| 430 | 430 |
| 431 uint32_t id = 0; | 431 uint32_t id = 0; |
| 432 { | 432 { |
| 433 MayAutoLock locker(&lock_); | 433 MayAutoLock locker(&lock_); |
| 434 // Relax the cross-thread access restriction to non-thread-safe RefCount. | |
| 435 // The lock above protects |endpoint|. | |
| 436 base::ScopedAllowCrossThreadRefCountAccess | |
|
yzshen1
2017/03/06 17:53:52
Can this opt-out be configured with a type (in thi
| |
| 437 allow_cross_thread_ref_count_access; | |
| 434 do { | 438 do { |
| 435 if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) | 439 if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) |
| 436 next_interface_id_value_ = 1; | 440 next_interface_id_value_ = 1; |
| 437 id = next_interface_id_value_++; | 441 id = next_interface_id_value_++; |
| 438 if (set_interface_id_namespace_bit_) | 442 if (set_interface_id_namespace_bit_) |
| 439 id |= kInterfaceIdNamespaceMask; | 443 id |= kInterfaceIdNamespaceMask; |
| 440 } while (base::ContainsKey(endpoints_, id)); | 444 } while (base::ContainsKey(endpoints_, id)); |
| 441 | 445 |
| 442 InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); | 446 InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); |
| 443 endpoints_[id] = endpoint; | 447 endpoints_[id] = endpoint; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 461 } | 465 } |
| 462 return id; | 466 return id; |
| 463 } | 467 } |
| 464 | 468 |
| 465 ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( | 469 ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( |
| 466 InterfaceId id) { | 470 InterfaceId id) { |
| 467 if (!IsValidInterfaceId(id)) | 471 if (!IsValidInterfaceId(id)) |
| 468 return ScopedInterfaceEndpointHandle(); | 472 return ScopedInterfaceEndpointHandle(); |
| 469 | 473 |
| 470 MayAutoLock locker(&lock_); | 474 MayAutoLock locker(&lock_); |
| 475 // Relax the cross-thread access restriction to non-thread-safe RefCount. | |
| 476 // The lock above protects |endpoint|. | |
| 477 base::ScopedAllowCrossThreadRefCountAccess | |
| 478 allow_cross_thread_ref_count_access; | |
| 471 bool inserted = false; | 479 bool inserted = false; |
| 472 InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); | 480 InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); |
| 473 if (inserted) { | 481 if (inserted) { |
| 474 DCHECK(!endpoint->handle_created()); | 482 DCHECK(!endpoint->handle_created()); |
| 475 | 483 |
| 476 if (encountered_error_) | 484 if (encountered_error_) |
| 477 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); | 485 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); |
| 478 } else { | 486 } else { |
| 479 // If the endpoint already exist, it is because we have received a | 487 // If the endpoint already exist, it is because we have received a |
| 480 // notification that the peer endpoint has closed. | 488 // notification that the peer endpoint has closed. |
| 481 CHECK(!endpoint->closed()); | 489 CHECK(!endpoint->closed()); |
| 482 CHECK(endpoint->peer_closed()); | 490 CHECK(endpoint->peer_closed()); |
| 483 | 491 |
| 484 if (endpoint->handle_created()) | 492 if (endpoint->handle_created()) |
| 485 return ScopedInterfaceEndpointHandle(); | 493 return ScopedInterfaceEndpointHandle(); |
| 486 } | 494 } |
| 487 | 495 |
| 488 endpoint->set_handle_created(); | 496 endpoint->set_handle_created(); |
| 489 return CreateScopedInterfaceEndpointHandle(id); | 497 return CreateScopedInterfaceEndpointHandle(id); |
| 490 } | 498 } |
| 491 | 499 |
| 492 void MultiplexRouter::CloseEndpointHandle( | 500 void MultiplexRouter::CloseEndpointHandle( |
| 493 InterfaceId id, | 501 InterfaceId id, |
| 494 const base::Optional<DisconnectReason>& reason) { | 502 const base::Optional<DisconnectReason>& reason) { |
| 495 if (!IsValidInterfaceId(id)) | 503 if (!IsValidInterfaceId(id)) |
| 496 return; | 504 return; |
| 497 | 505 |
| 498 MayAutoLock locker(&lock_); | 506 MayAutoLock locker(&lock_); |
| 507 // Relax the cross-thread access restriction to non-thread-safe RefCount. | |
| 508 // The lock above protects |endpoint|. | |
| 509 base::ScopedAllowCrossThreadRefCountAccess | |
| 510 allow_cross_thread_ref_count_access; | |
| 499 DCHECK(base::ContainsKey(endpoints_, id)); | 511 DCHECK(base::ContainsKey(endpoints_, id)); |
| 500 InterfaceEndpoint* endpoint = endpoints_[id].get(); | 512 InterfaceEndpoint* endpoint = endpoints_[id].get(); |
| 501 DCHECK(!endpoint->client()); | 513 DCHECK(!endpoint->client()); |
| 502 DCHECK(!endpoint->closed()); | 514 DCHECK(!endpoint->closed()); |
| 503 UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); | 515 UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); |
| 504 | 516 |
| 505 if (!IsMasterInterfaceId(id) || reason) { | 517 if (!IsMasterInterfaceId(id) || reason) { |
| 506 MayAutoUnlock unlocker(&lock_); | 518 MayAutoUnlock unlocker(&lock_); |
| 507 control_message_proxy_.NotifyPeerEndpointClosed(id, reason); | 519 control_message_proxy_.NotifyPeerEndpointClosed(id, reason); |
| 508 } | 520 } |
| 509 | 521 |
| 510 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); | 522 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); |
| 511 } | 523 } |
| 512 | 524 |
| 513 InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( | 525 InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( |
| 514 const ScopedInterfaceEndpointHandle& handle, | 526 const ScopedInterfaceEndpointHandle& handle, |
| 515 InterfaceEndpointClient* client, | 527 InterfaceEndpointClient* client, |
| 516 scoped_refptr<base::SingleThreadTaskRunner> runner) { | 528 scoped_refptr<base::SingleThreadTaskRunner> runner) { |
| 517 const InterfaceId id = handle.id(); | 529 const InterfaceId id = handle.id(); |
| 518 | 530 |
| 519 DCHECK(IsValidInterfaceId(id)); | 531 DCHECK(IsValidInterfaceId(id)); |
| 520 DCHECK(client); | 532 DCHECK(client); |
| 521 | 533 |
| 522 MayAutoLock locker(&lock_); | 534 MayAutoLock locker(&lock_); |
| 535 // Relax the cross-thread access restriction to non-thread-safe RefCount. | |
| 536 // The lock above protects |endpoint|. | |
| 537 base::ScopedAllowCrossThreadRefCountAccess | |
| 538 allow_cross_thread_ref_count_access; | |
| 523 DCHECK(base::ContainsKey(endpoints_, id)); | 539 DCHECK(base::ContainsKey(endpoints_, id)); |
| 524 | 540 |
| 525 InterfaceEndpoint* endpoint = endpoints_[id].get(); | 541 InterfaceEndpoint* endpoint = endpoints_[id].get(); |
| 526 endpoint->AttachClient(client, std::move(runner)); | 542 endpoint->AttachClient(client, std::move(runner)); |
| 527 | 543 |
| 528 if (endpoint->peer_closed()) | 544 if (endpoint->peer_closed()) |
| 529 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); | 545 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); |
| 530 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); | 546 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); |
| 531 | 547 |
| 532 return endpoint; | 548 return endpoint; |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 685 // No need to trigger a ProcessTasks() because it is already on the stack. | 701 // No need to trigger a ProcessTasks() because it is already on the stack. |
| 686 | 702 |
| 687 return true; | 703 return true; |
| 688 } | 704 } |
| 689 | 705 |
| 690 void MultiplexRouter::OnPipeConnectionError() { | 706 void MultiplexRouter::OnPipeConnectionError() { |
| 691 DCHECK(thread_checker_.CalledOnValidThread()); | 707 DCHECK(thread_checker_.CalledOnValidThread()); |
| 692 | 708 |
| 693 scoped_refptr<MultiplexRouter> protector(this); | 709 scoped_refptr<MultiplexRouter> protector(this); |
| 694 MayAutoLock locker(&lock_); | 710 MayAutoLock locker(&lock_); |
| 711 // Relax the cross-thread access restriction to non-thread-safe RefCount. | |
| 712 // The lock above protects |endpoint|. | |
| 713 base::ScopedAllowCrossThreadRefCountAccess | |
| 714 allow_cross_thread_ref_count_access; | |
| 695 | 715 |
| 696 encountered_error_ = true; | 716 encountered_error_ = true; |
| 697 | 717 |
| 698 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { | 718 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { |
| 699 InterfaceEndpoint* endpoint = iter->second.get(); | 719 InterfaceEndpoint* endpoint = iter->second.get(); |
| 700 // Increment the iterator before calling UpdateEndpointStateMayRemove() | 720 // Increment the iterator before calling UpdateEndpointStateMayRemove() |
| 701 // because it may remove the corresponding value from the map. | 721 // because it may remove the corresponding value from the map. |
| 702 ++iter; | 722 ++iter; |
| 703 | 723 |
| 704 if (endpoint->client()) | 724 if (endpoint->client()) |
| 705 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); | 725 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); |
| 706 | 726 |
| 707 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); | 727 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); |
| 708 } | 728 } |
| 709 | 729 |
| 710 ProcessTasks(connector_.during_sync_handle_watcher_callback() | 730 ProcessTasks(connector_.during_sync_handle_watcher_callback() |
| 711 ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES | 731 ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES |
| 712 : ALLOW_DIRECT_CLIENT_CALLS, | 732 : ALLOW_DIRECT_CLIENT_CALLS, |
| 713 connector_.task_runner()); | 733 connector_.task_runner()); |
| 714 } | 734 } |
| 715 | 735 |
| 716 void MultiplexRouter::ProcessTasks( | 736 void MultiplexRouter::ProcessTasks( |
| 717 ClientCallBehavior client_call_behavior, | 737 ClientCallBehavior client_call_behavior, |
| 718 base::SingleThreadTaskRunner* current_task_runner) { | 738 base::SingleThreadTaskRunner* current_task_runner) { |
| 719 AssertLockAcquired(); | 739 AssertLockAcquired(); |
| 740 // Relax the cross-thread access restriction to non-thread-safe RefCount. | |
| 741 // The lock above protects |endpoint|. | |
| 742 base::ScopedAllowCrossThreadRefCountAccess | |
| 743 allow_cross_thread_ref_count_access; | |
| 720 | 744 |
| 721 if (posted_to_process_tasks_) | 745 if (posted_to_process_tasks_) |
| 722 return; | 746 return; |
| 723 | 747 |
| 724 while (!tasks_.empty() && !paused_) { | 748 while (!tasks_.empty() && !paused_) { |
| 725 std::unique_ptr<Task> task(std::move(tasks_.front())); | 749 std::unique_ptr<Task> task(std::move(tasks_.front())); |
| 726 tasks_.pop_front(); | 750 tasks_.pop_front(); |
| 727 | 751 |
| 728 InterfaceId id = kInvalidInterfaceId; | 752 InterfaceId id = kInvalidInterfaceId; |
| 729 bool sync_message = | 753 bool sync_message = |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 977 | 1001 |
| 978 void MultiplexRouter::AssertLockAcquired() { | 1002 void MultiplexRouter::AssertLockAcquired() { |
| 979 #if DCHECK_IS_ON() | 1003 #if DCHECK_IS_ON() |
| 980 if (lock_) | 1004 if (lock_) |
| 981 lock_->AssertAcquired(); | 1005 lock_->AssertAcquired(); |
| 982 #endif | 1006 #endif |
| 983 } | 1007 } |
| 984 | 1008 |
| 985 } // namespace internal | 1009 } // namespace internal |
| 986 } // namespace mojo | 1010 } // namespace mojo |
| OLD | NEW |