| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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.h" | 5 #include "base/message_loop.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 // static | 71 // static |
| 72 MessageLoop* MessageLoop::current() { | 72 MessageLoop* MessageLoop::current() { |
| 73 // TODO(darin): sadly, we cannot enable this yet since people call us even | 73 // TODO(darin): sadly, we cannot enable this yet since people call us even |
| 74 // when they have no intention of using us. | 74 // when they have no intention of using us. |
| 75 //DCHECK(loop) << "Ouch, did you forget to initialize me?"; | 75 //DCHECK(loop) << "Ouch, did you forget to initialize me?"; |
| 76 return lazy_tls_ptr.Pointer()->Get(); | 76 return lazy_tls_ptr.Pointer()->Get(); |
| 77 } | 77 } |
| 78 | 78 |
| 79 MessageLoop::MessageLoop(Type type) | 79 MessageLoop::MessageLoop(Type type) |
| 80 : type_(type), | 80 : type_(type), |
| 81 work_queue_(new TaskQueue), |
| 81 nestable_tasks_allowed_(true), | 82 nestable_tasks_allowed_(true), |
| 82 exception_restoration_(false), | 83 exception_restoration_(false), |
| 84 incoming_queue_(new TaskQueue), |
| 83 state_(NULL), | 85 state_(NULL), |
| 84 next_sequence_num_(0) { | 86 next_sequence_num_(0) { |
| 85 DCHECK(!current()) << "should only have one message loop per thread"; | 87 DCHECK(!current()) << "should only have one message loop per thread"; |
| 86 lazy_tls_ptr.Pointer()->Set(this); | 88 lazy_tls_ptr.Pointer()->Set(this); |
| 87 | 89 |
| 88 #if defined(OS_WIN) | 90 #if defined(OS_WIN) |
| 89 // TODO(rvargas): Get rid of the OS guards. | 91 // TODO(rvargas): Get rid of the OS guards. |
| 90 if (type_ == TYPE_DEFAULT) { | 92 if (type_ == TYPE_DEFAULT) { |
| 91 pump_ = new base::MessagePumpDefault(); | 93 pump_ = new base::MessagePumpDefault(); |
| 92 } else if (type_ == TYPE_IO) { | 94 } else if (type_ == TYPE_IO) { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 } | 265 } |
| 264 | 266 |
| 265 // Warning: Don't try to short-circuit, and handle this thread's tasks more | 267 // Warning: Don't try to short-circuit, and handle this thread's tasks more |
| 266 // directly, as it could starve handling of foreign threads. Put every task | 268 // directly, as it could starve handling of foreign threads. Put every task |
| 267 // into this queue. | 269 // into this queue. |
| 268 | 270 |
| 269 scoped_refptr<base::MessagePump> pump; | 271 scoped_refptr<base::MessagePump> pump; |
| 270 { | 272 { |
| 271 AutoLock locked(incoming_queue_lock_); | 273 AutoLock locked(incoming_queue_lock_); |
| 272 | 274 |
| 273 bool was_empty = incoming_queue_.empty(); | 275 bool was_empty = incoming_queue_->empty(); |
| 274 incoming_queue_.push(pending_task); | 276 incoming_queue_->push(pending_task); |
| 275 if (!was_empty) | 277 if (!was_empty) |
| 276 return; // Someone else should have started the sub-pump. | 278 return; // Someone else should have started the sub-pump. |
| 277 | 279 |
| 278 pump = pump_; | 280 pump = pump_; |
| 279 } | 281 } |
| 280 // Since the incoming_queue_ may contain a task that destroys this message | 282 // Since the incoming_queue_ may contain a task that destroys this message |
| 281 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. | 283 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. |
| 282 // We use a stack-based reference to the message pump so that we can call | 284 // We use a stack-based reference to the message pump so that we can call |
| 283 // ScheduleWork outside of incoming_queue_lock_. | 285 // ScheduleWork outside of incoming_queue_lock_. |
| 284 | 286 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 PendingTask new_pending_task(pending_task); | 341 PendingTask new_pending_task(pending_task); |
| 340 new_pending_task.sequence_num = next_sequence_num_++; | 342 new_pending_task.sequence_num = next_sequence_num_++; |
| 341 delayed_work_queue_.push(new_pending_task); | 343 delayed_work_queue_.push(new_pending_task); |
| 342 } | 344 } |
| 343 | 345 |
| 344 void MessageLoop::ReloadWorkQueue() { | 346 void MessageLoop::ReloadWorkQueue() { |
| 345 // We can improve performance of our loading tasks from incoming_queue_ to | 347 // We can improve performance of our loading tasks from incoming_queue_ to |
| 346 // work_queue_ by waiting until the last minute (work_queue_ is empty) to | 348 // work_queue_ by waiting until the last minute (work_queue_ is empty) to |
| 347 // load. That reduces the number of locks-per-task significantly when our | 349 // load. That reduces the number of locks-per-task significantly when our |
| 348 // queues get large. | 350 // queues get large. |
| 349 if (!work_queue_.empty()) | 351 if (!work_queue_->empty()) |
| 350 return; // Wait till we *really* need to lock and load. | 352 return; // Wait till we *really* need to lock and load. |
| 351 | 353 |
| 352 // Acquire all we can from the inter-thread queue with one lock acquisition. | 354 // Acquire all we can from the inter-thread queue with one lock acquisition. |
| 353 { | 355 { |
| 354 AutoLock lock(incoming_queue_lock_); | 356 AutoLock lock(incoming_queue_lock_); |
| 355 if (incoming_queue_.empty()) | 357 if (incoming_queue_->empty()) |
| 356 return; | 358 return; |
| 357 std::swap(incoming_queue_, work_queue_); | 359 // std::queue does not define a swap specialization. Swap the pointers. |
| 358 DCHECK(incoming_queue_.empty()); | 360 incoming_queue_.swap(work_queue_); |
| 361 DCHECK(incoming_queue_->empty()); |
| 359 } | 362 } |
| 360 } | 363 } |
| 361 | 364 |
| 362 bool MessageLoop::DeletePendingTasks() { | 365 bool MessageLoop::DeletePendingTasks() { |
| 363 bool did_work = !work_queue_.empty(); | 366 bool did_work = !work_queue_->empty(); |
| 364 while (!work_queue_.empty()) { | 367 while (!work_queue_->empty()) { |
| 365 PendingTask pending_task = work_queue_.front(); | 368 PendingTask pending_task = work_queue_->front(); |
| 366 work_queue_.pop(); | 369 work_queue_->pop(); |
| 367 if (!pending_task.delayed_run_time.is_null()) { | 370 if (!pending_task.delayed_run_time.is_null()) { |
| 368 // We want to delete delayed tasks in the same order in which they would | 371 // We want to delete delayed tasks in the same order in which they would |
| 369 // normally be deleted in case of any funny dependencies between delayed | 372 // normally be deleted in case of any funny dependencies between delayed |
| 370 // tasks. | 373 // tasks. |
| 371 AddToDelayedWorkQueue(pending_task); | 374 AddToDelayedWorkQueue(pending_task); |
| 372 } else { | 375 } else { |
| 373 // TODO(darin): Delete all tasks once it is safe to do so. | 376 // TODO(darin): Delete all tasks once it is safe to do so. |
| 374 // Until it is totally safe, just do it when running Purify or | 377 // Until it is totally safe, just do it when running Purify or |
| 375 // Valgrind. | 378 // Valgrind. |
| 376 #if defined(PURIFY) | 379 #if defined(PURIFY) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 406 } | 409 } |
| 407 | 410 |
| 408 bool MessageLoop::DoWork() { | 411 bool MessageLoop::DoWork() { |
| 409 if (!nestable_tasks_allowed_) { | 412 if (!nestable_tasks_allowed_) { |
| 410 // Task can't be executed right now. | 413 // Task can't be executed right now. |
| 411 return false; | 414 return false; |
| 412 } | 415 } |
| 413 | 416 |
| 414 for (;;) { | 417 for (;;) { |
| 415 ReloadWorkQueue(); | 418 ReloadWorkQueue(); |
| 416 if (work_queue_.empty()) | 419 if (work_queue_->empty()) |
| 417 break; | 420 break; |
| 418 | 421 |
| 419 // Execute oldest task. | 422 // Execute oldest task. |
| 420 do { | 423 do { |
| 421 PendingTask pending_task = work_queue_.front(); | 424 PendingTask pending_task = work_queue_->front(); |
| 422 work_queue_.pop(); | 425 work_queue_->pop(); |
| 423 if (!pending_task.delayed_run_time.is_null()) { | 426 if (!pending_task.delayed_run_time.is_null()) { |
| 424 AddToDelayedWorkQueue(pending_task); | 427 AddToDelayedWorkQueue(pending_task); |
| 425 // If we changed the topmost task, then it is time to re-schedule. | 428 // If we changed the topmost task, then it is time to re-schedule. |
| 426 if (delayed_work_queue_.top().task == pending_task.task) | 429 if (delayed_work_queue_.top().task == pending_task.task) |
| 427 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); | 430 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); |
| 428 } else { | 431 } else { |
| 429 if (DeferOrRunPendingTask(pending_task)) | 432 if (DeferOrRunPendingTask(pending_task)) |
| 430 return true; | 433 return true; |
| 431 } | 434 } |
| 432 } while (!work_queue_.empty()); | 435 } while (!work_queue_->empty()); |
| 433 } | 436 } |
| 434 | 437 |
| 435 // Nothing happened. | 438 // Nothing happened. |
| 436 return false; | 439 return false; |
| 437 } | 440 } |
| 438 | 441 |
| 439 bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) { | 442 bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) { |
| 440 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) { | 443 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) { |
| 441 *next_delayed_work_time = Time(); | 444 *next_delayed_work_time = Time(); |
| 442 return false; | 445 return false; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 Watcher *delegate) { | 625 Watcher *delegate) { |
| 623 return pump_libevent()->WatchFileDescriptor( | 626 return pump_libevent()->WatchFileDescriptor( |
| 624 fd, | 627 fd, |
| 625 persistent, | 628 persistent, |
| 626 static_cast<base::MessagePumpLibevent::Mode>(mode), | 629 static_cast<base::MessagePumpLibevent::Mode>(mode), |
| 627 controller, | 630 controller, |
| 628 delegate); | 631 delegate); |
| 629 } | 632 } |
| 630 | 633 |
| 631 #endif | 634 #endif |
| OLD | NEW |