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

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

Issue 2880453003: Introduce RunLoop::Delegate splitting RunLoop/MessageLoop some more. (Closed)
Patch Set: Created 3 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_loop.h" 5 #include "base/message_loop/message_loop.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 MessageLoop::~MessageLoop() { 90 MessageLoop::~MessageLoop() {
91 // If |pump_| is non-null, this message loop has been bound and should be the 91 // If |pump_| is non-null, this message loop has been bound and should be the
92 // current one on this thread. Otherwise, this loop is being destructed before 92 // current one on this thread. Otherwise, this loop is being destructed before
93 // it was bound to a thread, so a different message loop (or no loop at all) 93 // it was bound to a thread, so a different message loop (or no loop at all)
94 // may be current. 94 // may be current.
95 DCHECK((pump_ && current() == this) || (!pump_ && current() != this)); 95 DCHECK((pump_ && current() == this) || (!pump_ && current() != this));
96 96
97 // iOS just attaches to the loop, it doesn't Run it. 97 // iOS just attaches to the loop, it doesn't Run it.
98 // TODO(stuartmorgan): Consider wiring up a Detach(). 98 // TODO(stuartmorgan): Consider wiring up a Detach().
99 #if !defined(OS_IOS) 99 #if !defined(OS_IOS)
100 DCHECK(!run_loop_); 100 // There should be no active RunLoops on this thread, unless this MessageLoop
101 // isn't bound to the current thread (see other condition at the top of this
102 // method).
103 DCHECK((!pump_ && current() != this) || !GetTopMostRunLoop());
101 #endif 104 #endif
102 105
103 #if defined(OS_WIN) 106 #if defined(OS_WIN)
104 if (in_high_res_mode_) 107 if (in_high_res_mode_)
105 Time::ActivateHighResolutionTimer(false); 108 Time::ActivateHighResolutionTimer(false);
106 #endif 109 #endif
107 // Clean up any unprocessed tasks, but take care: deleting a task could 110 // Clean up any unprocessed tasks, but take care: deleting a task could
108 // result in the addition of more tasks (e.g., via DeleteSoon). We set a 111 // result in the addition of more tasks (e.g., via DeleteSoon). We set a
109 // limit on the number of times we will allow a deleted task to generate more 112 // limit on the number of times we will allow a deleted task to generate more
110 // tasks. Normally, we should only pass through this loop once or twice. If 113 // tasks. Normally, we should only pass through this loop once or twice. If
(...skipping 18 matching lines...) Expand all
129 132
130 // Tell the incoming queue that we are dying. 133 // Tell the incoming queue that we are dying.
131 incoming_task_queue_->WillDestroyCurrentMessageLoop(); 134 incoming_task_queue_->WillDestroyCurrentMessageLoop();
132 incoming_task_queue_ = NULL; 135 incoming_task_queue_ = NULL;
133 unbound_task_runner_ = NULL; 136 unbound_task_runner_ = NULL;
134 task_runner_ = NULL; 137 task_runner_ = NULL;
135 138
136 // OK, now make it so that no one can find us. 139 // OK, now make it so that no one can find us.
137 if (current() == this) 140 if (current() == this)
138 GetTLSMessageLoop()->Set(nullptr); 141 GetTLSMessageLoop()->Set(nullptr);
139
140 RunLoop::ResetTLSState();
141 } 142 }
142 143
143 // static 144 // static
144 MessageLoop* MessageLoop::current() { 145 MessageLoop* MessageLoop::current() {
145 // TODO(darin): sadly, we cannot enable this yet since people call us even 146 // TODO(darin): sadly, we cannot enable this yet since people call us even
146 // when they have no intention of using us. 147 // when they have no intention of using us.
147 // DCHECK(loop) << "Ouch, did you forget to initialize me?"; 148 // DCHECK(loop) << "Ouch, did you forget to initialize me?";
148 return GetTLSMessageLoop()->Get(); 149 return GetTLSMessageLoop()->Get();
149 } 150 }
150 151
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 } 210 }
210 211
211 void MessageLoop::RemoveDestructionObserver( 212 void MessageLoop::RemoveDestructionObserver(
212 DestructionObserver* destruction_observer) { 213 DestructionObserver* destruction_observer) {
213 DCHECK_EQ(this, current()); 214 DCHECK_EQ(this, current());
214 destruction_observers_.RemoveObserver(destruction_observer); 215 destruction_observers_.RemoveObserver(destruction_observer);
215 } 216 }
216 217
217 void MessageLoop::QuitWhenIdle() { 218 void MessageLoop::QuitWhenIdle() {
218 DCHECK_EQ(this, current()); 219 DCHECK_EQ(this, current());
219 if (run_loop_) { 220 DCHECK(GetTopMostRunLoop()) << "Must be inside Run to call QuitWhenIdle";
220 run_loop_->QuitWhenIdle(); 221 GetTopMostRunLoop()->QuitWhenIdle();
221 } else {
222 NOTREACHED() << "Must be inside Run to call QuitWhenIdle";
223 }
224 } 222 }
225 223
226 void MessageLoop::QuitNow() { 224 void MessageLoop::QuitNow() {
227 DCHECK_EQ(this, current()); 225 DCHECK_EQ(this, current());
228 if (run_loop_) { 226 DCHECK(GetTopMostRunLoop()) << "Must be inside Run to call Quit";
229 pump_->Quit(); 227 pump_->Quit();
230 } else {
231 NOTREACHED() << "Must be inside Run to call Quit";
232 }
233 } 228 }
234 229
235 bool MessageLoop::IsType(Type type) const { 230 bool MessageLoop::IsType(Type type) const {
236 return type_ == type; 231 return type_ == type;
237 } 232 }
238 233
239 static void QuitCurrentWhenIdle() { 234 static void QuitCurrentWhenIdle() {
240 MessageLoop::current()->QuitWhenIdle(); 235 MessageLoop::current()->QuitWhenIdle();
241 } 236 }
242 237
243 // static 238 // static
244 Closure MessageLoop::QuitWhenIdleClosure() { 239 Closure MessageLoop::QuitWhenIdleClosure() {
245 return Bind(&QuitCurrentWhenIdle); 240 return Bind(&QuitCurrentWhenIdle);
246 } 241 }
247 242
248 void MessageLoop::SetNestableTasksAllowed(bool allowed) { 243 void MessageLoop::SetNestableTasksAllowed(bool allowed) {
249 if (allowed) { 244 if (allowed) {
250 CHECK(base::RunLoop::IsNestingAllowedOnCurrentThread()); 245 CHECK(RunLoop::IsNestingAllowedOnCurrentThread());
251 246
252 // Kick the native pump just in case we enter a OS-driven nested message 247 // Kick the native pump just in case we enter a OS-driven nested message
253 // loop. 248 // loop.
254 pump_->ScheduleWork(); 249 pump_->ScheduleWork();
255 } 250 }
256 nestable_tasks_allowed_ = allowed; 251 nestable_tasks_allowed_ = allowed;
257 } 252 }
258 253
259 bool MessageLoop::NestableTasksAllowed() const { 254 bool MessageLoop::NestableTasksAllowed() const {
260 return nestable_tasks_allowed_; 255 return nestable_tasks_allowed_;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 } 290 }
296 291
297 MessageLoop::MessageLoop(Type type, MessagePumpFactoryCallback pump_factory) 292 MessageLoop::MessageLoop(Type type, MessagePumpFactoryCallback pump_factory)
298 : type_(type), 293 : type_(type),
299 #if defined(OS_WIN) 294 #if defined(OS_WIN)
300 pending_high_res_tasks_(0), 295 pending_high_res_tasks_(0),
301 in_high_res_mode_(false), 296 in_high_res_mode_(false),
302 #endif 297 #endif
303 nestable_tasks_allowed_(true), 298 nestable_tasks_allowed_(true),
304 pump_factory_(std::move(pump_factory)), 299 pump_factory_(std::move(pump_factory)),
305 run_loop_(nullptr),
306 current_pending_task_(nullptr), 300 current_pending_task_(nullptr),
307 incoming_task_queue_(new internal::IncomingTaskQueue(this)), 301 incoming_task_queue_(new internal::IncomingTaskQueue(this)),
308 unbound_task_runner_( 302 unbound_task_runner_(
309 new internal::MessageLoopTaskRunner(incoming_task_queue_)), 303 new internal::MessageLoopTaskRunner(incoming_task_queue_)),
310 task_runner_(unbound_task_runner_), 304 task_runner_(unbound_task_runner_),
311 thread_id_(kInvalidThreadId) { 305 thread_id_(kInvalidThreadId) {
312 // If type is TYPE_CUSTOM non-null pump_factory must be given. 306 // If type is TYPE_CUSTOM non-null pump_factory must be given.
313 DCHECK(type_ != TYPE_CUSTOM || !pump_factory_.is_null()); 307 DCHECK(type_ != TYPE_CUSTOM || !pump_factory_.is_null());
314 } 308 }
315 309
316 void MessageLoop::BindToCurrentThread() {
317 DCHECK(!pump_);
318 if (!pump_factory_.is_null())
319 pump_ = std::move(pump_factory_).Run();
320 else
321 pump_ = CreateMessagePumpForType(type_);
322
323 DCHECK(!current()) << "should only have one message loop per thread";
324 GetTLSMessageLoop()->Set(this);
325
326 incoming_task_queue_->StartScheduling();
327 unbound_task_runner_->BindToCurrentThread();
328 unbound_task_runner_ = nullptr;
329 SetThreadTaskRunnerHandle();
330 thread_id_ = PlatformThread::CurrentId();
331 }
332
333 std::string MessageLoop::GetThreadName() const { 310 std::string MessageLoop::GetThreadName() const {
334 DCHECK_NE(kInvalidThreadId, thread_id_) 311 DCHECK_NE(kInvalidThreadId, thread_id_)
335 << "GetThreadName() must only be called after BindToCurrentThread()'s " 312 << "GetThreadName() must only be called after BindToCurrentThread()'s "
336 << "side-effects have been synchronized with this thread."; 313 << "side-effects have been synchronized with this thread.";
337 return ThreadIdNameManager::GetInstance()->GetName(thread_id_); 314 return ThreadIdNameManager::GetInstance()->GetName(thread_id_);
338 } 315 }
339 316
340 void MessageLoop::SetTaskRunner( 317 void MessageLoop::SetTaskRunner(
341 scoped_refptr<SingleThreadTaskRunner> task_runner) { 318 scoped_refptr<SingleThreadTaskRunner> task_runner) {
342 DCHECK_EQ(this, current()); 319 DCHECK_EQ(this, current());
343 DCHECK(task_runner); 320 DCHECK(task_runner);
344 DCHECK(task_runner->BelongsToCurrentThread()); 321 DCHECK(task_runner->BelongsToCurrentThread());
345 DCHECK(!unbound_task_runner_); 322 DCHECK(!unbound_task_runner_);
346 task_runner_ = std::move(task_runner); 323 task_runner_ = std::move(task_runner);
347 SetThreadTaskRunnerHandle(); 324 SetThreadTaskRunnerHandle();
348 } 325 }
349 326
350 void MessageLoop::ClearTaskRunnerForTesting() { 327 void MessageLoop::ClearTaskRunnerForTesting() {
351 DCHECK_EQ(this, current()); 328 DCHECK_EQ(this, current());
352 DCHECK(!unbound_task_runner_); 329 DCHECK(!unbound_task_runner_);
353 task_runner_ = nullptr; 330 task_runner_ = nullptr;
354 thread_task_runner_handle_.reset(); 331 thread_task_runner_handle_.reset();
355 } 332 }
356 333
334 void MessageLoop::BindToCurrentThread() {
335 RunLoop::Delegate::BindToCurrentThread();
336
337 DCHECK(!pump_);
338 if (!pump_factory_.is_null())
339 pump_ = std::move(pump_factory_).Run();
340 else
341 pump_ = CreateMessagePumpForType(type_);
342
343 DCHECK(!current()) << "should only have one message loop per thread";
344 GetTLSMessageLoop()->Set(this);
345
346 incoming_task_queue_->StartScheduling();
347 unbound_task_runner_->BindToCurrentThread();
348 unbound_task_runner_ = nullptr;
349 SetThreadTaskRunnerHandle();
350 thread_id_ = PlatformThread::CurrentId();
351 }
352
353 void MessageLoop::Run() {
354 DCHECK_EQ(this, current());
355 pump_->Run(this);
356 }
357
358 void MessageLoop::Quit() {
359 DCHECK_EQ(this, current());
360 QuitNow();
361 }
362
357 void MessageLoop::SetThreadTaskRunnerHandle() { 363 void MessageLoop::SetThreadTaskRunnerHandle() {
358 DCHECK_EQ(this, current()); 364 DCHECK_EQ(this, current());
359 // Clear the previous thread task runner first, because only one can exist at 365 // Clear the previous thread task runner first, because only one can exist at
360 // a time. 366 // a time.
361 thread_task_runner_handle_.reset(); 367 thread_task_runner_handle_.reset();
362 thread_task_runner_handle_.reset(new ThreadTaskRunnerHandle(task_runner_)); 368 thread_task_runner_handle_.reset(new ThreadTaskRunnerHandle(task_runner_));
363 } 369 }
364 370
365 void MessageLoop::RunHandler() {
366 DCHECK_EQ(this, current());
367 DCHECK(run_loop_);
368 pump_->Run(this);
369 }
370
371 bool MessageLoop::ProcessNextDelayedNonNestableTask() { 371 bool MessageLoop::ProcessNextDelayedNonNestableTask() {
372 if (is_nested_) 372 if (IsNested())
373 return false; 373 return false;
374 374
375 if (deferred_non_nestable_work_queue_.empty()) 375 if (deferred_non_nestable_work_queue_.empty())
376 return false; 376 return false;
377 377
378 PendingTask pending_task = 378 PendingTask pending_task =
379 std::move(deferred_non_nestable_work_queue_.front()); 379 std::move(deferred_non_nestable_work_queue_.front());
380 deferred_non_nestable_work_queue_.pop(); 380 deferred_non_nestable_work_queue_.pop();
381 381
382 RunTask(&pending_task); 382 RunTask(&pending_task);
(...skipping 21 matching lines...) Expand all
404 task_annotator_.RunTask("MessageLoop::PostTask", pending_task); 404 task_annotator_.RunTask("MessageLoop::PostTask", pending_task);
405 for (auto& observer : task_observers_) 405 for (auto& observer : task_observers_)
406 observer.DidProcessTask(*pending_task); 406 observer.DidProcessTask(*pending_task);
407 407
408 nestable_tasks_allowed_ = true; 408 nestable_tasks_allowed_ = true;
409 409
410 current_pending_task_ = nullptr; 410 current_pending_task_ = nullptr;
411 } 411 }
412 412
413 bool MessageLoop::DeferOrRunPendingTask(PendingTask pending_task) { 413 bool MessageLoop::DeferOrRunPendingTask(PendingTask pending_task) {
414 if (pending_task.nestable || !is_nested_) { 414 if (pending_task.nestable || !IsNested()) {
415 RunTask(&pending_task); 415 RunTask(&pending_task);
416 // Show that we ran a task (Note: a new one might arrive as a 416 // Show that we ran a task (Note: a new one might arrive as a
417 // consequence!). 417 // consequence!).
418 return true; 418 return true;
419 } 419 }
420 420
421 // We couldn't run the task now because we're in a nested run loop 421 // We couldn't run the task now because we're in a nested run loop
422 // and the task isn't nestable. 422 // and the task isn't nestable.
423 deferred_non_nestable_work_queue_.push(std::move(pending_task)); 423 deferred_non_nestable_work_queue_.push(std::move(pending_task));
424 return false; 424 return false;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 if (!delayed_work_queue_.empty()) 539 if (!delayed_work_queue_.empty())
540 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; 540 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
541 541
542 return DeferOrRunPendingTask(std::move(pending_task)); 542 return DeferOrRunPendingTask(std::move(pending_task));
543 } 543 }
544 544
545 bool MessageLoop::DoIdleWork() { 545 bool MessageLoop::DoIdleWork() {
546 if (ProcessNextDelayedNonNestableTask()) 546 if (ProcessNextDelayedNonNestableTask())
547 return true; 547 return true;
548 548
549 if (run_loop_->quit_when_idle_received_) 549 if (GetTopMostRunLoop()->quit_when_idle_received_)
550 pump_->Quit(); 550 pump_->Quit();
551 551
552 // When we return we will do a kernel wait for more tasks. 552 // When we return we will do a kernel wait for more tasks.
553 #if defined(OS_WIN) 553 #if defined(OS_WIN)
554 // On Windows we activate the high resolution timer so that the wait 554 // On Windows we activate the high resolution timer so that the wait
555 // _if_ triggered by the timer happens with good resolution. If we don't 555 // _if_ triggered by the timer happens with good resolution. If we don't
556 // do this the default resolution is 15ms which might not be acceptable 556 // do this the default resolution is 15ms which might not be acceptable
557 // for some tasks. 557 // for some tasks.
558 bool high_res = pending_high_res_tasks_ > 0; 558 bool high_res = pending_high_res_tasks_ > 0;
559 if (high_res != in_high_res_mode_) { 559 if (high_res != in_high_res_mode_) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 persistent, 642 persistent,
643 mode, 643 mode,
644 controller, 644 controller,
645 delegate); 645 delegate);
646 } 646 }
647 #endif 647 #endif
648 648
649 #endif // !defined(OS_NACL_SFI) 649 #endif // !defined(OS_NACL_SFI)
650 650
651 } // namespace base 651 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698