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

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

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

Powered by Google App Engine
This is Rietveld 408576698