blob: db3f86e4622e09263684b64158eb7a5c181867c3 [file] [log] [blame]
jabdelmalek@google.comeb921652010-04-07 05:33:36 +09001// 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.
4
5#include "ipc/ipc_sync_message_filter.h"
6
7#include "base/logging.h"
8#include "base/message_loop.h"
9#include "ipc/ipc_sync_message.h"
10
11namespace IPC {
12
13SyncMessageFilter::SyncMessageFilter(base::WaitableEvent* shutdown_event)
14 : channel_(NULL),
15 listener_loop_(MessageLoop::current()),
16 io_loop_(NULL),
17 shutdown_event_(shutdown_event) {
18}
19
20SyncMessageFilter::~SyncMessageFilter() {
21}
22
23bool SyncMessageFilter::Send(Message* message) {
24 {
25 AutoLock auto_lock(lock_);
26 if (!io_loop_) {
27 delete message;
28 return false;
29 }
30 }
31
32 if (!message->is_sync()) {
33 io_loop_->PostTask(
34 FROM_HERE,
35 NewRunnableMethod(this, &SyncMessageFilter::SendOnIOThread, message));
36 return true;
37 }
38
39 base::WaitableEvent done_event(true, false);
40 PendingSyncMsg pending_message(
41 SyncMessage::GetMessageId(*message),
42 reinterpret_cast<SyncMessage*>(message)->GetReplyDeserializer(),
43 &done_event);
44
45 {
46 AutoLock auto_lock(lock_);
47 // Can't use this class on the main thread or else it can lead to deadlocks.
48 // Also by definition, can't use this on IO thread since we're blocking it.
49 DCHECK(MessageLoop::current() != listener_loop_);
50 DCHECK(MessageLoop::current() != io_loop_);
51 pending_sync_messages_[MessageLoop::current()] = &pending_message;
52 }
53
54 io_loop_->PostTask(
55 FROM_HERE,
56 NewRunnableMethod(this, &SyncMessageFilter::SendOnIOThread, message));
57
58 base::WaitableEvent* events[2] = { shutdown_event_, &done_event };
59 base::WaitableEvent::WaitMany(events, 2);
60
61 {
62 AutoLock auto_lock(lock_);
63 delete pending_message.deserializer;
64 pending_sync_messages_.erase(MessageLoop::current());
65 }
66
67 return pending_message.send_result;
68}
69
70void SyncMessageFilter::SendOnIOThread(Message* message) {
71 if (channel_) {
72 channel_->Send(message);
73 return;
74 }
75
76 if (message->is_sync()) {
77 // We don't know which thread sent it, but it doesn't matter, just signal
78 // them all.
79 SignalAllEvents();
80 }
81
82 delete message;
83}
84
85void SyncMessageFilter::SignalAllEvents() {
86 AutoLock auto_lock(lock_);
87 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
88 iter != pending_sync_messages_.end(); ++iter) {
89 iter->second->done_event->Signal();
90 }
91}
92
93void SyncMessageFilter::OnFilterAdded(Channel* channel) {
94 channel_ = channel;
95 AutoLock auto_lock(lock_);
96 io_loop_ = MessageLoop::current();
97}
98
99void SyncMessageFilter::OnChannelError() {
100 channel_ = NULL;
101 SignalAllEvents();
102}
103
104void SyncMessageFilter::OnChannelClosing() {
105 channel_ = NULL;
106 SignalAllEvents();
107}
108
109bool SyncMessageFilter::OnMessageReceived(const Message& message) {
110 AutoLock auto_lock(lock_);
111 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
112 iter != pending_sync_messages_.end(); ++iter) {
113 if (SyncMessage::IsMessageReplyTo(message, iter->second->id)) {
114 if (!message.is_reply_error()) {
115 iter->second->send_result =
116 iter->second->deserializer->SerializeOutputParameters(message);
117 }
118 iter->second->done_event->Signal();
119 return true;
120 }
121 }
122
123 return false;
124}
125
126} // namespace IPC