Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(560)

Side by Side Diff: chrome/common/ipc_sync_channel.cc

Issue 1660: Move a bunch of code from the old to new TLS interface. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/thread.cc ('k') | chrome/common/notification_service.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 <windows.h> 5 #include <windows.h>
6 6
7 #include "chrome/common/ipc_sync_channel.h" 7 #include "chrome/common/ipc_sync_channel.h"
8 8
9 #include "base/lazy_instance.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "base/thread_local_storage.h" 11 #include "base/thread_local.h"
11 #include "chrome/common/child_process.h" 12 #include "chrome/common/child_process.h"
12 #include "chrome/common/ipc_logging.h" 13 #include "chrome/common/ipc_logging.h"
13 #include "chrome/common/ipc_sync_message.h" 14 #include "chrome/common/ipc_sync_message.h"
14 15
15 16
16 namespace IPC { 17 namespace IPC {
17 // When we're blocked in a Send(), we need to process incoming synchronous 18 // When we're blocked in a Send(), we need to process incoming synchronous
18 // messages right away because it could be blocking our reply (either 19 // messages right away because it could be blocking our reply (either
19 // directly from the same object we're calling, or indirectly through one or 20 // directly from the same object we're calling, or indirectly through one or
20 // more other channels). That means that in SyncContext's OnMessageReceived, 21 // more other channels). That means that in SyncContext's OnMessageReceived,
21 // we need to process sync message right away if we're blocked. However a 22 // we need to process sync message right away if we're blocked. However a
22 // simple check isn't sufficient, because the listener thread can be in the 23 // simple check isn't sufficient, because the listener thread can be in the
23 // process of calling Send. 24 // process of calling Send.
24 // To work around this, when SyncChannel filters a sync message, it sets 25 // To work around this, when SyncChannel filters a sync message, it sets
25 // an event that the listener thread waits on during its Send() call. This 26 // an event that the listener thread waits on during its Send() call. This
26 // allows us to dispatch incoming sync messages when blocked. The race 27 // allows us to dispatch incoming sync messages when blocked. The race
27 // condition is handled because if Send is in the process of being called, it 28 // condition is handled because if Send is in the process of being called, it
28 // will check the event. In case the listener thread isn't sending a message, 29 // will check the event. In case the listener thread isn't sending a message,
29 // we queue a task on the listener thread to dispatch the received messages. 30 // we queue a task on the listener thread to dispatch the received messages.
30 // The messages are stored in this queue object that's shared among all 31 // The messages are stored in this queue object that's shared among all
31 // SyncChannel objects on the same thread (since one object can receive a 32 // SyncChannel objects on the same thread (since one object can receive a
32 // sync message while another one is blocked). 33 // sync message while another one is blocked).
33 34
34 // Holds a pointer to the per-thread ReceivedSyncMsgQueue object. 35 class SyncChannel::ReceivedSyncMsgQueue;
35 // TODO(evanm): this shouldn't rely on static initialization.
36 static TLSSlot g_tls_index;
37 36
38 class SyncChannel::ReceivedSyncMsgQueue : 37 class SyncChannel::ReceivedSyncMsgQueue :
39 public base::RefCountedThreadSafe<ReceivedSyncMsgQueue> { 38 public base::RefCountedThreadSafe<ReceivedSyncMsgQueue> {
40 public: 39 public:
41 ReceivedSyncMsgQueue() : 40 ReceivedSyncMsgQueue() :
42 blocking_event_(CreateEvent(NULL, FALSE, FALSE, NULL)), 41 blocking_event_(CreateEvent(NULL, FALSE, FALSE, NULL)),
43 task_pending_(false), 42 task_pending_(false),
44 listener_message_loop_(MessageLoop::current()) { 43 listener_message_loop_(MessageLoop::current()) {
45 } 44 }
46 45
47 ~ReceivedSyncMsgQueue() { 46 ~ReceivedSyncMsgQueue() {
48 DCHECK(g_tls_index.Get()); 47 DCHECK(lazy_tls_ptr_.Pointer()->Get());
49 DCHECK(MessageLoop::current() == listener_message_loop_); 48 DCHECK(MessageLoop::current() == listener_message_loop_);
50 CloseHandle(blocking_event_); 49 CloseHandle(blocking_event_);
51 g_tls_index.Set(NULL); 50 lazy_tls_ptr_.Pointer()->Set(NULL);
52 } 51 }
53 52
54 // Called on IPC thread when a synchronous message or reply arrives. 53 // Called on IPC thread when a synchronous message or reply arrives.
55 void QueueMessage(const Message& msg, Channel::Listener* listener, 54 void QueueMessage(const Message& msg, Channel::Listener* listener,
56 const std::wstring& channel_id) { 55 const std::wstring& channel_id) {
57 bool was_task_pending; 56 bool was_task_pending;
58 { 57 {
59 AutoLock auto_lock(message_lock_); 58 AutoLock auto_lock(message_lock_);
60 59
61 was_task_pending = task_pending_; 60 was_task_pending = task_pending_;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 147
149 while (!temp_queue.empty()) { 148 while (!temp_queue.empty()) {
150 message_queue_.push(temp_queue.front()); 149 message_queue_.push(temp_queue.front());
151 temp_queue.pop(); 150 temp_queue.pop();
152 } 151 }
153 } 152 }
154 153
155 HANDLE blocking_event() { return blocking_event_; } 154 HANDLE blocking_event() { return blocking_event_; }
156 MessageLoop* listener_message_loop() { return listener_message_loop_; } 155 MessageLoop* listener_message_loop() { return listener_message_loop_; }
157 156
157 // Holds a pointer to the per-thread ReceivedSyncMsgQueue object.
158 static base::LazyInstance<base::ThreadLocalPointer<ReceivedSyncMsgQueue> >
159 lazy_tls_ptr_;
160
158 private: 161 private:
159 // Called on the ipc thread to check if we can unblock any current Send() 162 // Called on the ipc thread to check if we can unblock any current Send()
160 // calls based on a queued reply. 163 // calls based on a queued reply.
161 void DispatchReplies() { 164 void DispatchReplies() {
162 for (size_t i = 0; i < received_replies_.size(); ++i) { 165 for (size_t i = 0; i < received_replies_.size(); ++i) {
163 Message* message = received_replies_[i].message; 166 Message* message = received_replies_[i].message;
164 if (received_replies_[i].context->UnblockListener(message)) { 167 if (received_replies_[i].context->UnblockListener(message)) {
165 delete message; 168 delete message;
166 received_replies_.erase(received_replies_.begin() + i); 169 received_replies_.erase(received_replies_.begin() + i);
167 return; 170 return;
(...skipping 28 matching lines...) Expand all
196 : message(m), 199 : message(m),
197 context(c) { } 200 context(c) { }
198 201
199 Message* message; 202 Message* message;
200 scoped_refptr<SyncChannel::SyncContext> context; 203 scoped_refptr<SyncChannel::SyncContext> context;
201 }; 204 };
202 205
203 std::vector<Reply> received_replies_; 206 std::vector<Reply> received_replies_;
204 }; 207 };
205 208
209 base::LazyInstance<base::ThreadLocalPointer<SyncChannel::ReceivedSyncMsgQueue> >
210 SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_(base::LINKER_INITIALIZED);
206 211
207 SyncChannel::SyncContext::SyncContext( 212 SyncChannel::SyncContext::SyncContext(
208 Channel::Listener* listener, 213 Channel::Listener* listener,
209 MessageFilter* filter, 214 MessageFilter* filter,
210 MessageLoop* ipc_thread) 215 MessageLoop* ipc_thread)
211 : ChannelProxy::Context(listener, filter, ipc_thread), 216 : ChannelProxy::Context(listener, filter, ipc_thread),
212 channel_closed_(false), 217 channel_closed_(false),
213 reply_deserialize_result_(false) { 218 reply_deserialize_result_(false) {
214 // We want one ReceivedSyncMsgQueue per listener thread (i.e. since multiple 219 // We want one ReceivedSyncMsgQueue per listener thread (i.e. since multiple
215 // SyncChannel objects that can block the same thread). 220 // SyncChannel objects that can block the same thread).
216 received_sync_msgs_ = static_cast<ReceivedSyncMsgQueue*>(g_tls_index.Get()); 221 received_sync_msgs_ = ReceivedSyncMsgQueue::lazy_tls_ptr_.Pointer()->Get();
217 222
218 if (!received_sync_msgs_) { 223 if (!received_sync_msgs_) {
219 // Stash a pointer to the listener thread's ReceivedSyncMsgQueue, as we 224 // Stash a pointer to the listener thread's ReceivedSyncMsgQueue, as we
220 // need to be able to access it in the IPC thread. 225 // need to be able to access it in the IPC thread.
221 received_sync_msgs_ = new ReceivedSyncMsgQueue(); 226 received_sync_msgs_ = new ReceivedSyncMsgQueue();
222 g_tls_index.Set(received_sync_msgs_); 227 ReceivedSyncMsgQueue::lazy_tls_ptr_.Pointer()->Set(received_sync_msgs_);
223 } 228 }
224 229
225 // Addref manually so that we can ensure destruction on the listener thread 230 // Addref manually so that we can ensure destruction on the listener thread
226 // (so that the TLS object is NULLd). 231 // (so that the TLS object is NULLd).
227 received_sync_msgs_->AddRef(); 232 received_sync_msgs_->AddRef();
228 } 233 }
229 234
230 SyncChannel::SyncContext::~SyncContext() { 235 SyncChannel::SyncContext::~SyncContext() {
231 while (!deserializers_.empty()) 236 while (!deserializers_.empty())
232 PopDeserializer(true); 237 PopDeserializer(true);
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 // or we time-out. 477 // or we time-out.
473 } while (true); 478 } while (true);
474 } 479 }
475 480
476 bool SyncChannel::UnblockListener(Message* message) { 481 bool SyncChannel::UnblockListener(Message* message) {
477 return sync_context()->UnblockListener(message); 482 return sync_context()->UnblockListener(message);
478 } 483 }
479 484
480 } // namespace IPC 485 } // namespace IPC
481 486
OLDNEW
« no previous file with comments | « base/thread.cc ('k') | chrome/common/notification_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698