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

Side by Side Diff: base/message_loop/message_pump_glib.cc

Issue 289043010: Makes MessagePumpGlib thread DCHECK work when pump is destroyed (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cleanup Created 6 years, 7 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 | « no previous file | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/message_loop/message_pump_glib.h" 5 #include "base/message_loop/message_pump_glib.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <math.h> 8 #include <math.h>
9 9
10 #include <glib.h> 10 #include <glib.h>
11 11
12 #include "base/lazy_instance.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/posix/eintr_wrapper.h" 14 #include "base/posix/eintr_wrapper.h"
15 #include "base/synchronization/lock.h"
14 #include "base/threading/platform_thread.h" 16 #include "base/threading/platform_thread.h"
15 17
16 namespace base { 18 namespace base {
17 19
18 namespace { 20 namespace {
19 21
20 // Return a timeout suitable for the glib loop, -1 to block forever, 22 // Return a timeout suitable for the glib loop, -1 to block forever,
21 // 0 to return right away, or a timeout in milliseconds from now. 23 // 0 to return right away, or a timeout in milliseconds from now.
22 int GetTimeIntervalMilliseconds(const TimeTicks& from) { 24 int GetTimeIntervalMilliseconds(const TimeTicks& from) {
23 if (from.is_null()) 25 if (from.is_null())
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 } 112 }
111 113
112 // I wish these could be const, but g_source_new wants non-const. 114 // I wish these could be const, but g_source_new wants non-const.
113 GSourceFuncs WorkSourceFuncs = { 115 GSourceFuncs WorkSourceFuncs = {
114 WorkSourcePrepare, 116 WorkSourcePrepare,
115 WorkSourceCheck, 117 WorkSourceCheck,
116 WorkSourceDispatch, 118 WorkSourceDispatch,
117 NULL 119 NULL
118 }; 120 };
119 121
122 // The following is used to make sure we only run the MessagePumpGlib on one
123 // thread. X only has one message pump so we can only have one UI loop per
124 // process.
125 #ifndef NDEBUG
126
127 // Tracks the pump the most recent pump that has been run.
128 struct ThreadInfo {
129 // The pump.
130 MessagePumpGlib* pump;
131
132 // ID of the thread the pump was run on.
133 PlatformThreadId thread_id;
134 };
135
136 // Used for accesing |thread_info|.
137 static LazyInstance<Lock>::Leaky thread_info_lock = LAZY_INSTANCE_INITIALIZER;
138
139 // If non-NULL it means a MessagePumpGlib exists and has been Run. This is
140 // destroyed when the MessagePump is destroyed.
141 ThreadInfo* thread_info = NULL;
142
143 void CheckThread(MessagePumpGlib* pump) {
144 AutoLock auto_lock(thread_info_lock.Get());
145 if (!thread_info) {
146 thread_info = new ThreadInfo;
147 thread_info->pump = pump;
148 thread_info->thread_id = PlatformThread::CurrentId();
149 }
150 DCHECK(thread_info->thread_id == PlatformThread::CurrentId()) <<
151 "Running MessagePumpGlib on two different threads; "
152 "this is unsupported by GLib!";
153 }
154
155 void PumpDestroyed(MessagePumpGlib* pump) {
156 AutoLock auto_lock(thread_info_lock.Get());
157 if (thread_info && thread_info->pump == pump) {
sadrul 2014/05/23 21:29:58 Shouldn't thread_info->pump be always be == pump?
sky 2014/05/23 21:54:37 I believe so, but I wanted to make sure if that is
darin (slow to review) 2014/05/23 23:25:13 You might consider a CHECK here. Did you consider
sky 2014/05/27 15:57:27 This is all to verify we don't start MessagePumpGl
158 delete thread_info;
159 thread_info = NULL;
160 }
161 }
162
163 #endif
164
120 } // namespace 165 } // namespace
121 166
122 struct MessagePumpGlib::RunState { 167 struct MessagePumpGlib::RunState {
123 Delegate* delegate; 168 Delegate* delegate;
124 169
125 // Used to flag that the current Run() invocation should return ASAP. 170 // Used to flag that the current Run() invocation should return ASAP.
126 bool should_quit; 171 bool should_quit;
127 172
128 // Used to count how many Run() invocations are on the stack. 173 // Used to count how many Run() invocations are on the stack.
129 int run_depth; 174 int run_depth;
(...skipping 23 matching lines...) Expand all
153 static_cast<WorkSource*>(work_source_)->pump = this; 198 static_cast<WorkSource*>(work_source_)->pump = this;
154 g_source_add_poll(work_source_, wakeup_gpollfd_.get()); 199 g_source_add_poll(work_source_, wakeup_gpollfd_.get());
155 // Use a low priority so that we let other events in the queue go first. 200 // Use a low priority so that we let other events in the queue go first.
156 g_source_set_priority(work_source_, G_PRIORITY_DEFAULT_IDLE); 201 g_source_set_priority(work_source_, G_PRIORITY_DEFAULT_IDLE);
157 // This is needed to allow Run calls inside Dispatch. 202 // This is needed to allow Run calls inside Dispatch.
158 g_source_set_can_recurse(work_source_, TRUE); 203 g_source_set_can_recurse(work_source_, TRUE);
159 g_source_attach(work_source_, context_); 204 g_source_attach(work_source_, context_);
160 } 205 }
161 206
162 MessagePumpGlib::~MessagePumpGlib() { 207 MessagePumpGlib::~MessagePumpGlib() {
208 #ifndef NDEBUG
209 PumpDestroyed(this);
210 #endif
163 g_source_destroy(work_source_); 211 g_source_destroy(work_source_);
164 g_source_unref(work_source_); 212 g_source_unref(work_source_);
165 close(wakeup_pipe_read_); 213 close(wakeup_pipe_read_);
166 close(wakeup_pipe_write_); 214 close(wakeup_pipe_write_);
167 } 215 }
168 216
169 // Return the timeout we want passed to poll. 217 // Return the timeout we want passed to poll.
170 int MessagePumpGlib::HandlePrepare() { 218 int MessagePumpGlib::HandlePrepare() {
171 // We know we have work, but we haven't called HandleDispatch yet. Don't let 219 // We know we have work, but we haven't called HandleDispatch yet. Don't let
172 // the pump block so that we can do some processing. 220 // the pump block so that we can do some processing.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 } 273 }
226 274
227 if (state_->should_quit) 275 if (state_->should_quit)
228 return; 276 return;
229 277
230 state_->delegate->DoDelayedWork(&delayed_work_time_); 278 state_->delegate->DoDelayedWork(&delayed_work_time_);
231 } 279 }
232 280
233 void MessagePumpGlib::Run(Delegate* delegate) { 281 void MessagePumpGlib::Run(Delegate* delegate) {
234 #ifndef NDEBUG 282 #ifndef NDEBUG
235 // Make sure we only run this on one thread. X only has one message pump 283 CheckThread(this);
236 // so we can only have one UI loop per process.
237 static PlatformThreadId thread_id = PlatformThread::CurrentId();
238 DCHECK(thread_id == PlatformThread::CurrentId()) <<
239 "Running MessagePumpGlib on two different threads; "
240 "this is unsupported by GLib!";
241 #endif 284 #endif
242 285
243 RunState state; 286 RunState state;
244 state.delegate = delegate; 287 state.delegate = delegate;
245 state.should_quit = false; 288 state.should_quit = false;
246 state.run_depth = state_ ? state_->run_depth + 1 : 1; 289 state.run_depth = state_ ? state_->run_depth + 1 : 1;
247 state.has_work = false; 290 state.has_work = false;
248 291
249 RunState* previous_state = state_; 292 RunState* previous_state = state_;
250 state_ = &state; 293 state_ = &state;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 delayed_work_time_ = delayed_work_time; 354 delayed_work_time_ = delayed_work_time;
312 ScheduleWork(); 355 ScheduleWork();
313 } 356 }
314 357
315 bool MessagePumpGlib::ShouldQuit() const { 358 bool MessagePumpGlib::ShouldQuit() const {
316 CHECK(state_); 359 CHECK(state_);
317 return state_->should_quit; 360 return state_->should_quit;
318 } 361 }
319 362
320 } // namespace base 363 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698