OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |