Index: ipc/ipc_sync_channel.cc |
diff --git a/ipc/ipc_sync_channel.cc b/ipc/ipc_sync_channel.cc |
index f3c538421386a3fc03c076501e4b7d7eb10be632..20a77c51d225c4866483e6e7b1d849a07fec5fc4 100644 |
--- a/ipc/ipc_sync_channel.cc |
+++ b/ipc/ipc_sync_channel.cc |
@@ -64,6 +64,7 @@ class SyncChannel::ReceivedSyncMsgQueue : |
// We set the event in case the listener thread is blocked (or is about |
// to). In case it's not, the PostTask dispatches the messages. |
message_queue_.push_back(QueuedMessage(new Message(msg), context)); |
+ message_queue_version_++; |
} |
dispatch_event_.Signal(); |
@@ -89,27 +90,35 @@ class SyncChannel::ReceivedSyncMsgQueue : |
} |
void DispatchMessages(SyncContext* dispatching_context) { |
- SyncMessageQueue delayed_queue; |
+ bool first_time = true; |
+ uint32 expected_version = 0; |
+ SyncMessageQueue::iterator it; |
while (true) { |
- Message* message; |
+ Message* message = NULL; |
scoped_refptr<SyncChannel::SyncContext> context; |
{ |
base::AutoLock auto_lock(message_lock_); |
- if (message_queue_.empty()) { |
- message_queue_ = delayed_queue; |
- break; |
+ if (first_time || message_queue_version_ != expected_version) { |
+ it = message_queue_.begin(); |
+ first_time = false; |
+ } |
+ for (; it != message_queue_.end(); it++) { |
+ if (!it->context->restrict_dispatch() || |
+ it->context == dispatching_context) { |
+ message = it->message; |
+ context = it->context; |
+ it = message_queue_.erase(it); |
+ message_queue_version_++; |
+ expected_version = message_queue_version_; |
+ break; |
+ } |
} |
- |
- message = message_queue_.front().message; |
- context = message_queue_.front().context; |
- message_queue_.pop_front(); |
- } |
- if (context->restrict_dispatch() && context != dispatching_context) { |
- delayed_queue.push_back(QueuedMessage(message, context)); |
- } else { |
- context->OnDispatchMessage(*message); |
- delete message; |
} |
+ |
+ if (message == NULL) |
+ break; |
+ context->OnDispatchMessage(*message); |
+ delete message; |
} |
} |
@@ -122,6 +131,7 @@ class SyncChannel::ReceivedSyncMsgQueue : |
if (iter->context == context) { |
delete iter->message; |
iter = message_queue_.erase(iter); |
+ message_queue_version_++; |
} else { |
iter++; |
} |
@@ -169,6 +179,7 @@ class SyncChannel::ReceivedSyncMsgQueue : |
// See the comment in SyncChannel::SyncChannel for why this event is created |
// as manual reset. |
ReceivedSyncMsgQueue() : |
+ message_queue_version_(0), |
dispatch_event_(true, false), |
listener_message_loop_(base::MessageLoopProxy::current()), |
task_pending_(false), |
@@ -185,8 +196,9 @@ class SyncChannel::ReceivedSyncMsgQueue : |
scoped_refptr<SyncChannel::SyncContext> context; |
}; |
- typedef std::deque<QueuedMessage> SyncMessageQueue; |
+ typedef std::list<QueuedMessage> SyncMessageQueue; |
SyncMessageQueue message_queue_; |
+ uint32 message_queue_version_; // Used to signal DispatchMessages to rescan |
std::vector<QueuedMessage> received_replies_; |