OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/bind.h" |
7 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
8 #include "base/location.h" | 9 #include "base/location.h" |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
10 #include "base/threading/thread_local.h" | 11 #include "base/threading/thread_local.h" |
11 #include "base/synchronization/waitable_event.h" | 12 #include "base/synchronization/waitable_event.h" |
12 #include "base/synchronization/waitable_event_watcher.h" | 13 #include "base/synchronization/waitable_event_watcher.h" |
13 #include "ipc/ipc_sync_message.h" | 14 #include "ipc/ipc_sync_message.h" |
14 | 15 |
15 using base::TimeDelta; | 16 using base::TimeDelta; |
16 using base::TimeTicks; | 17 using base::TimeTicks; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 was_task_pending = task_pending_; | 61 was_task_pending = task_pending_; |
61 task_pending_ = true; | 62 task_pending_ = true; |
62 | 63 |
63 // We set the event in case the listener thread is blocked (or is about | 64 // We set the event in case the listener thread is blocked (or is about |
64 // to). In case it's not, the PostTask dispatches the messages. | 65 // to). In case it's not, the PostTask dispatches the messages. |
65 message_queue_.push_back(QueuedMessage(new Message(msg), context)); | 66 message_queue_.push_back(QueuedMessage(new Message(msg), context)); |
66 } | 67 } |
67 | 68 |
68 dispatch_event_.Signal(); | 69 dispatch_event_.Signal(); |
69 if (!was_task_pending) { | 70 if (!was_task_pending) { |
70 listener_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 71 listener_message_loop_->PostTask( |
71 this, | 72 FROM_HERE, base::Bind(&ReceivedSyncMsgQueue::DispatchMessagesTask, |
72 &ReceivedSyncMsgQueue::DispatchMessagesTask, | 73 this, scoped_refptr<SyncContext>(context))); |
73 scoped_refptr<SyncContext>(context))); | |
74 } | 74 } |
75 } | 75 } |
76 | 76 |
77 void QueueReply(const Message &msg, SyncChannel::SyncContext* context) { | 77 void QueueReply(const Message &msg, SyncChannel::SyncContext* context) { |
78 received_replies_.push_back(QueuedMessage(new Message(msg), context)); | 78 received_replies_.push_back(QueuedMessage(new Message(msg), context)); |
79 } | 79 } |
80 | 80 |
81 // Called on the listener's thread to process any queues synchronous | 81 // Called on the listener's thread to process any queues synchronous |
82 // messages. | 82 // messages. |
83 void DispatchMessagesTask(SyncContext* context) { | 83 void DispatchMessagesTask(SyncContext* context) { |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 msg.done_event = NULL; | 252 msg.done_event = NULL; |
253 deserializers_.pop_back(); | 253 deserializers_.pop_back(); |
254 result = msg.send_result; | 254 result = msg.send_result; |
255 } | 255 } |
256 | 256 |
257 // We got a reply to a synchronous Send() call that's blocking the listener | 257 // We got a reply to a synchronous Send() call that's blocking the listener |
258 // thread. However, further down the call stack there could be another | 258 // thread. However, further down the call stack there could be another |
259 // blocking Send() call, whose reply we received after we made this last | 259 // blocking Send() call, whose reply we received after we made this last |
260 // Send() call. So check if we have any queued replies available that | 260 // Send() call. So check if we have any queued replies available that |
261 // can now unblock the listener thread. | 261 // can now unblock the listener thread. |
262 ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 262 ipc_message_loop()->PostTask( |
263 received_sync_msgs_.get(), &ReceivedSyncMsgQueue::DispatchReplies)); | 263 FROM_HERE, base::Bind(&ReceivedSyncMsgQueue::DispatchReplies, |
| 264 received_sync_msgs_.get())); |
264 | 265 |
265 return result; | 266 return result; |
266 } | 267 } |
267 | 268 |
268 WaitableEvent* SyncChannel::SyncContext::GetSendDoneEvent() { | 269 WaitableEvent* SyncChannel::SyncContext::GetSendDoneEvent() { |
269 base::AutoLock auto_lock(deserializers_lock_); | 270 base::AutoLock auto_lock(deserializers_lock_); |
270 return deserializers_.back().done_event; | 271 return deserializers_.back().done_event; |
271 } | 272 } |
272 | 273 |
273 WaitableEvent* SyncChannel::SyncContext::GetDispatchEvent() { | 274 WaitableEvent* SyncChannel::SyncContext::GetDispatchEvent() { |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 context->Push(sync_msg); | 421 context->Push(sync_msg); |
421 int message_id = SyncMessage::GetMessageId(*sync_msg); | 422 int message_id = SyncMessage::GetMessageId(*sync_msg); |
422 WaitableEvent* pump_messages_event = sync_msg->pump_messages_event(); | 423 WaitableEvent* pump_messages_event = sync_msg->pump_messages_event(); |
423 | 424 |
424 ChannelProxy::Send(message); | 425 ChannelProxy::Send(message); |
425 | 426 |
426 if (timeout_ms != base::kNoTimeout) { | 427 if (timeout_ms != base::kNoTimeout) { |
427 // We use the sync message id so that when a message times out, we don't | 428 // We use the sync message id so that when a message times out, we don't |
428 // confuse it with another send that is either above/below this Send in | 429 // confuse it with another send that is either above/below this Send in |
429 // the call stack. | 430 // the call stack. |
430 context->ipc_message_loop()->PostDelayedTask(FROM_HERE, | 431 context->ipc_message_loop()->PostDelayedTask( |
431 NewRunnableMethod(context.get(), | 432 FROM_HERE, |
432 &SyncContext::OnSendTimeout, message_id), timeout_ms); | 433 base::Bind(&SyncContext::OnSendTimeout, context.get(), message_id), |
| 434 timeout_ms); |
433 } | 435 } |
434 | 436 |
435 // Wait for reply, or for any other incoming synchronous messages. | 437 // Wait for reply, or for any other incoming synchronous messages. |
436 // *this* might get deleted, so only call static functions at this point. | 438 // *this* might get deleted, so only call static functions at this point. |
437 WaitForReply(context, pump_messages_event); | 439 WaitForReply(context, pump_messages_event); |
438 | 440 |
439 return context->Pop(); | 441 return context->Pop(); |
440 } | 442 } |
441 | 443 |
442 void SyncChannel::WaitForReply( | 444 void SyncChannel::WaitForReply( |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 void SyncChannel::OnWaitableEventSignaled(WaitableEvent* event) { | 507 void SyncChannel::OnWaitableEventSignaled(WaitableEvent* event) { |
506 DCHECK(event == sync_context()->GetDispatchEvent()); | 508 DCHECK(event == sync_context()->GetDispatchEvent()); |
507 // The call to DispatchMessages might delete this object, so reregister | 509 // The call to DispatchMessages might delete this object, so reregister |
508 // the object watcher first. | 510 // the object watcher first. |
509 event->Reset(); | 511 event->Reset(); |
510 dispatch_watcher_.StartWatching(event, this); | 512 dispatch_watcher_.StartWatching(event, this); |
511 sync_context()->DispatchMessages(); | 513 sync_context()->DispatchMessages(); |
512 } | 514 } |
513 | 515 |
514 } // namespace IPC | 516 } // namespace IPC |
OLD | NEW |