WebKit Roll 77251:77261.
[chromium-blink-merge.git] / ipc / ipc_sync_message_filter.cc
blobcffbaa674aedd88bad0d9ae239476f8055aa5cb4
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ipc/ipc_sync_message_filter.h"
7 #include "base/logging.h"
8 #include "base/message_loop.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "ipc/ipc_sync_message.h"
12 namespace IPC {
14 SyncMessageFilter::SyncMessageFilter(base::WaitableEvent* shutdown_event)
15 : channel_(NULL),
16 listener_loop_(MessageLoop::current()),
17 io_loop_(NULL),
18 shutdown_event_(shutdown_event) {
21 SyncMessageFilter::~SyncMessageFilter() {
24 bool SyncMessageFilter::Send(Message* message) {
26 base::AutoLock auto_lock(lock_);
27 if (!io_loop_) {
28 delete message;
29 return false;
33 if (!message->is_sync()) {
34 io_loop_->PostTask(
35 FROM_HERE,
36 NewRunnableMethod(this, &SyncMessageFilter::SendOnIOThread, message));
37 return true;
40 base::WaitableEvent done_event(true, false);
41 PendingSyncMsg pending_message(
42 SyncMessage::GetMessageId(*message),
43 reinterpret_cast<SyncMessage*>(message)->GetReplyDeserializer(),
44 &done_event);
47 base::AutoLock auto_lock(lock_);
48 // Can't use this class on the main thread or else it can lead to deadlocks.
49 // Also by definition, can't use this on IO thread since we're blocking it.
50 DCHECK(MessageLoop::current() != listener_loop_);
51 DCHECK(MessageLoop::current() != io_loop_);
52 pending_sync_messages_.insert(&pending_message);
55 io_loop_->PostTask(
56 FROM_HERE,
57 NewRunnableMethod(this, &SyncMessageFilter::SendOnIOThread, message));
59 base::WaitableEvent* events[2] = { shutdown_event_, &done_event };
60 base::WaitableEvent::WaitMany(events, 2);
63 base::AutoLock auto_lock(lock_);
64 delete pending_message.deserializer;
65 pending_sync_messages_.erase(&pending_message);
68 return pending_message.send_result;
71 void SyncMessageFilter::SendOnIOThread(Message* message) {
72 if (channel_) {
73 channel_->Send(message);
74 return;
77 if (message->is_sync()) {
78 // We don't know which thread sent it, but it doesn't matter, just signal
79 // them all.
80 SignalAllEvents();
83 delete message;
86 void SyncMessageFilter::SignalAllEvents() {
87 base::AutoLock auto_lock(lock_);
88 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
89 iter != pending_sync_messages_.end(); ++iter) {
90 (*iter)->done_event->Signal();
94 void SyncMessageFilter::OnFilterAdded(Channel* channel) {
95 channel_ = channel;
96 base::AutoLock auto_lock(lock_);
97 io_loop_ = MessageLoop::current();
100 void SyncMessageFilter::OnChannelError() {
101 channel_ = NULL;
102 SignalAllEvents();
105 void SyncMessageFilter::OnChannelClosing() {
106 channel_ = NULL;
107 SignalAllEvents();
110 bool SyncMessageFilter::OnMessageReceived(const Message& message) {
111 base::AutoLock auto_lock(lock_);
112 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
113 iter != pending_sync_messages_.end(); ++iter) {
114 if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) {
115 if (!message.is_reply_error()) {
116 (*iter)->send_result =
117 (*iter)->deserializer->SerializeOutputParameters(message);
119 (*iter)->done_event->Signal();
120 return true;
124 return false;
127 } // namespace IPC