| 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 |