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 |