| 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 |