Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: ipc/ipc_sync_channel.cc

Issue 2081963003: Simplify SyncChannel message pumping event (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ipc/ipc_sync_channel.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ipc/ipc_sync_channel.h" 5 #include "ipc/ipc_sync_channel.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <utility> 10 #include <utility>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 42
43 // A ReadyCallback for use with mojo::Watcher. Ignores the result (DCHECKs, but 43 // A ReadyCallback for use with mojo::Watcher. Ignores the result (DCHECKs, but
44 // is only used in cases where failure should be impossible) and runs 44 // is only used in cases where failure should be impossible) and runs
45 // |callback|. 45 // |callback|.
46 void RunOnHandleReady(const base::Closure& callback, MojoResult result) { 46 void RunOnHandleReady(const base::Closure& callback, MojoResult result) {
47 DCHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_ABORTED); 47 DCHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_ABORTED);
48 if (result == MOJO_RESULT_OK) 48 if (result == MOJO_RESULT_OK)
49 callback.Run(); 49 callback.Run();
50 } 50 }
51 51
52 } // namespace 52 class PumpMessagesEvent {
53
54 // A lazy thread-local Mojo Event which is always signaled. Used to wake up the
55 // sync waiter when a SyncMessage requires the MessageLoop to be pumped while
56 // waiting for a reply. This object is created lazily and ref-counted so it can
57 // be cleaned up when no longer in use.
58 class SyncChannel::PumpMessagesEvent
59 : public base::RefCountedThreadSafe<PumpMessagesEvent> {
60 public: 53 public:
61 static scoped_refptr<PumpMessagesEvent> current() { 54 PumpMessagesEvent() { event_.Signal(); }
62 scoped_refptr<PumpMessagesEvent> current = current_event_.Pointer()->Get(); 55 ~PumpMessagesEvent() {}
63 if (!current) {
64 current = new PumpMessagesEvent;
65 current_event_.Pointer()->Set(current.get());
66 }
67 return current;
68 }
69 56
70 const MojoEvent* event() const { return &event_; } 57 const MojoEvent* event() const { return &event_; }
71 58
72 private: 59 private:
73 friend class base::RefCountedThreadSafe<PumpMessagesEvent>;
74
75 PumpMessagesEvent() { event_.Signal(); }
76
77 ~PumpMessagesEvent() {
78 DCHECK_EQ(current_event_.Pointer()->Get(), this);
79 current_event_.Pointer()->Set(nullptr);
80 }
81
82 MojoEvent event_; 60 MojoEvent event_;
83 61
84 static base::LazyInstance<base::ThreadLocalPointer<
85 SyncChannel::PumpMessagesEvent>> current_event_;
86
87 DISALLOW_COPY_AND_ASSIGN(PumpMessagesEvent); 62 DISALLOW_COPY_AND_ASSIGN(PumpMessagesEvent);
88 }; 63 };
89 64
90 base::LazyInstance<base::ThreadLocalPointer<SyncChannel::PumpMessagesEvent>> 65 base::LazyInstance<PumpMessagesEvent>::Leaky g_pump_messages_event =
91 SyncChannel::PumpMessagesEvent::current_event_ = 66 LAZY_INSTANCE_INITIALIZER;
92 LAZY_INSTANCE_INITIALIZER;
93 67
68 } // namespace
94 69
95 // When we're blocked in a Send(), we need to process incoming synchronous 70 // When we're blocked in a Send(), we need to process incoming synchronous
96 // messages right away because it could be blocking our reply (either 71 // messages right away because it could be blocking our reply (either
97 // directly from the same object we're calling, or indirectly through one or 72 // directly from the same object we're calling, or indirectly through one or
98 // more other channels). That means that in SyncContext's OnMessageReceived, 73 // more other channels). That means that in SyncContext's OnMessageReceived,
99 // we need to process sync message right away if we're blocked. However a 74 // we need to process sync message right away if we're blocked. However a
100 // simple check isn't sufficient, because the listener thread can be in the 75 // simple check isn't sufficient, because the listener thread can be in the
101 // process of calling Send. 76 // process of calling Send.
102 // To work around this, when SyncChannel filters a sync message, it sets 77 // To work around this, when SyncChannel filters a sync message, it sets
103 // an event that the listener thread waits on during its Send() call. This 78 // an event that the listener thread waits on during its Send() call. This
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 WaitableEvent* shutdown_event) { 471 WaitableEvent* shutdown_event) {
497 return base::WrapUnique( 472 return base::WrapUnique(
498 new SyncChannel(listener, ipc_task_runner, shutdown_event)); 473 new SyncChannel(listener, ipc_task_runner, shutdown_event));
499 } 474 }
500 475
501 SyncChannel::SyncChannel( 476 SyncChannel::SyncChannel(
502 Listener* listener, 477 Listener* listener,
503 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, 478 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
504 WaitableEvent* shutdown_event) 479 WaitableEvent* shutdown_event)
505 : ChannelProxy(new SyncContext(listener, ipc_task_runner, shutdown_event)), 480 : ChannelProxy(new SyncContext(listener, ipc_task_runner, shutdown_event)),
506 pump_messages_event_(PumpMessagesEvent::current()),
507 sync_handle_registry_(mojo::SyncHandleRegistry::current()) { 481 sync_handle_registry_(mojo::SyncHandleRegistry::current()) {
508 // The current (listener) thread must be distinct from the IPC thread, or else 482 // The current (listener) thread must be distinct from the IPC thread, or else
509 // sending synchronous messages will deadlock. 483 // sending synchronous messages will deadlock.
510 DCHECK_NE(ipc_task_runner.get(), base::ThreadTaskRunnerHandle::Get().get()); 484 DCHECK_NE(ipc_task_runner.get(), base::ThreadTaskRunnerHandle::Get().get());
511 StartWatching(); 485 StartWatching();
512 } 486 }
513 487
514 SyncChannel::~SyncChannel() { 488 SyncChannel::~SyncChannel() {
515 } 489 }
516 490
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 DVLOG(1) << "Channel is shutting down. Dropping sync message."; 526 DVLOG(1) << "Channel is shutting down. Dropping sync message.";
553 delete message; 527 delete message;
554 return false; 528 return false;
555 } 529 }
556 530
557 ChannelProxy::Send(message); 531 ChannelProxy::Send(message);
558 532
559 // Wait for reply, or for any other incoming synchronous messages. 533 // Wait for reply, or for any other incoming synchronous messages.
560 // *this* might get deleted, so only call static functions at this point. 534 // *this* might get deleted, so only call static functions at this point.
561 scoped_refptr<mojo::SyncHandleRegistry> registry = sync_handle_registry_; 535 scoped_refptr<mojo::SyncHandleRegistry> registry = sync_handle_registry_;
562 scoped_refptr<PumpMessagesEvent> pump_messages_event = pump_messages_event_; 536 WaitForReply(registry.get(), context.get(), pump_messages);
563 WaitForReply(registry.get(), context.get(),
564 pump_messages ? pump_messages_event->event() : nullptr);
565 537
566 TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), 538 TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
567 "SyncChannel::Send", context->GetSendDoneEvent()); 539 "SyncChannel::Send", context->GetSendDoneEvent());
568 540
569 return context->Pop(); 541 return context->Pop();
570 } 542 }
571 543
572 void SyncChannel::WaitForReply(mojo::SyncHandleRegistry* registry, 544 void SyncChannel::WaitForReply(mojo::SyncHandleRegistry* registry,
573 SyncContext* context, 545 SyncContext* context,
574 const MojoEvent* pump_messages_event) { 546 bool pump_messages) {
575 context->DispatchMessages(); 547 context->DispatchMessages();
576 548
549 const MojoEvent* pump_messages_event = nullptr;
550 if (pump_messages)
551 pump_messages_event = g_pump_messages_event.Get().event();
552
577 while (true) { 553 while (true) {
578 bool dispatch = false; 554 bool dispatch = false;
579 bool send_done = false; 555 bool send_done = false;
580 bool should_pump_messages = false; 556 bool should_pump_messages = false;
581 bool error = false; 557 bool error = false;
582 registry->RegisterHandle(context->GetDispatchEvent()->GetHandle(), 558 registry->RegisterHandle(context->GetDispatchEvent()->GetHandle(),
583 MOJO_HANDLE_SIGNAL_READABLE, 559 MOJO_HANDLE_SIGNAL_READABLE,
584 base::Bind(&OnSyncHandleReady, &dispatch, &error)); 560 base::Bind(&OnSyncHandleReady, &dispatch, &error));
585 registry->RegisterHandle( 561 registry->RegisterHandle(
586 context->GetSendDoneEvent()->GetHandle(), 562 context->GetSendDoneEvent()->GetHandle(),
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 650
675 void SyncChannel::OnChannelInit() { 651 void SyncChannel::OnChannelInit() {
676 for (const auto& filter : pre_init_sync_message_filters_) { 652 for (const auto& filter : pre_init_sync_message_filters_) {
677 filter->set_is_channel_send_thread_safe( 653 filter->set_is_channel_send_thread_safe(
678 context()->IsChannelSendThreadSafe()); 654 context()->IsChannelSendThreadSafe());
679 } 655 }
680 pre_init_sync_message_filters_.clear(); 656 pre_init_sync_message_filters_.clear();
681 } 657 }
682 658
683 } // namespace IPC 659 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_sync_channel.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698