| OLD | NEW | 
|    1 // Copyright 2015 The Chromium Authors. All rights reserved. |    1 // Copyright 2015 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 "platform/scheduler/base/task_queue_impl.h" |    5 #include "platform/scheduler/base/task_queue_impl.h" | 
|    6  |    6  | 
|    7 #include "base/format_macros.h" |    7 #include "base/format_macros.h" | 
 |    8 #include "base/memory/ptr_util.h" | 
|    8 #include "base/strings/stringprintf.h" |    9 #include "base/strings/stringprintf.h" | 
|    9 #include "base/trace_event/blame_context.h" |   10 #include "base/trace_event/blame_context.h" | 
|   10 #include "platform/scheduler/base/task_queue_manager.h" |   11 #include "platform/scheduler/base/task_queue_manager.h" | 
|   11 #include "platform/scheduler/base/task_queue_manager_delegate.h" |   12 #include "platform/scheduler/base/task_queue_manager_delegate.h" | 
|   12 #include "platform/scheduler/base/time_domain.h" |   13 #include "platform/scheduler/base/time_domain.h" | 
|   13 #include "platform/scheduler/base/work_queue.h" |   14 #include "platform/scheduler/base/work_queue.h" | 
|   14  |   15  | 
|   15 namespace blink { |   16 namespace blink { | 
|   16 namespace scheduler { |   17 namespace scheduler { | 
|   17  |   18  | 
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  149  |  150  | 
|  150 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |  151 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 
|  151     TaskQueueManager* task_queue_manager, |  152     TaskQueueManager* task_queue_manager, | 
|  152     TaskQueueImpl* task_queue, |  153     TaskQueueImpl* task_queue, | 
|  153     TimeDomain* time_domain) |  154     TimeDomain* time_domain) | 
|  154     : task_queue_manager(task_queue_manager), |  155     : task_queue_manager(task_queue_manager), | 
|  155       time_domain(time_domain), |  156       time_domain(time_domain), | 
|  156       delayed_work_queue(new WorkQueue(task_queue, "delayed")), |  157       delayed_work_queue(new WorkQueue(task_queue, "delayed")), | 
|  157       immediate_work_queue(new WorkQueue(task_queue, "immediate")), |  158       immediate_work_queue(new WorkQueue(task_queue, "immediate")), | 
|  158       set_index(0), |  159       set_index(0), | 
|  159       is_enabled(true), |  160       is_enabled_refcount(0), | 
 |  161       voter_refcount(0), | 
|  160       blame_context(nullptr), |  162       blame_context(nullptr), | 
|  161       current_fence(0) {} |  163       current_fence(0) {} | 
|  162  |  164  | 
|  163 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |  165 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 
|  164  |  166  | 
|  165 void TaskQueueImpl::UnregisterTaskQueue() { |  167 void TaskQueueImpl::UnregisterTaskQueue() { | 
|  166   base::AutoLock lock(any_thread_lock_); |  168   base::AutoLock lock(any_thread_lock_); | 
|  167   if (main_thread_only().time_domain) |  169   if (main_thread_only().time_domain) | 
|  168     main_thread_only().time_domain->UnregisterQueue(this); |  170     main_thread_only().time_domain->UnregisterQueue(this); | 
|  169   if (!any_thread().task_queue_manager) |  171   if (!any_thread().task_queue_manager) | 
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  325     EnqueueOrder sequence_number, |  327     EnqueueOrder sequence_number, | 
|  326     bool nestable) { |  328     bool nestable) { | 
|  327   if (any_thread().immediate_incoming_queue.empty()) |  329   if (any_thread().immediate_incoming_queue.empty()) | 
|  328     any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |  330     any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 
|  329   // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |  331   // If the |immediate_incoming_queue| is empty we need a DoWork posted to make | 
|  330   // it run. |  332   // it run. | 
|  331   if (any_thread().immediate_incoming_queue.empty()) { |  333   if (any_thread().immediate_incoming_queue.empty()) { | 
|  332     // There's no point posting a DoWork for a disabled queue, however we can |  334     // There's no point posting a DoWork for a disabled queue, however we can | 
|  333     // only tell if it's disabled from the main thread. |  335     // only tell if it's disabled from the main thread. | 
|  334     if (base::PlatformThread::CurrentId() == thread_id_) { |  336     if (base::PlatformThread::CurrentId() == thread_id_) { | 
|  335       if (main_thread_only().is_enabled && !BlockedByFenceLocked()) |  337       if (IsQueueEnabled() && !BlockedByFenceLocked()) | 
|  336         any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |  338         any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 
|  337     } else { |  339     } else { | 
|  338       any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |  340       any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 
|  339     } |  341     } | 
|  340   } |  342   } | 
|  341   any_thread().immediate_incoming_queue.emplace( |  343   any_thread().immediate_incoming_queue.emplace( | 
|  342       posted_from, task, desired_run_time, sequence_number, nestable, sequence_n
     umber); |  344       posted_from, task, desired_run_time, sequence_number, nestable, sequence_n
     umber); | 
|  343   any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming
     _queue.back()); |  345   any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming
     _queue.back()); | 
|  344   TraceQueueSize(true); |  346   TraceQueueSize(true); | 
|  345 } |  347 } | 
|  346  |  348  | 
|  347 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |  | 
|  348   if (main_thread_only().is_enabled == enabled) |  | 
|  349     return; |  | 
|  350   main_thread_only().is_enabled = enabled; |  | 
|  351   if (!main_thread_only().task_queue_manager) |  | 
|  352     return; |  | 
|  353   if (enabled) { |  | 
|  354     // Note it's the job of the selector to tell the TaskQueueManager if |  | 
|  355     // a DoWork needs posting. |  | 
|  356     main_thread_only().task_queue_manager->selector_.EnableQueue(this); |  | 
|  357   } else { |  | 
|  358     main_thread_only().task_queue_manager->selector_.DisableQueue(this); |  | 
|  359   } |  | 
|  360 } |  | 
|  361  |  | 
|  362 bool TaskQueueImpl::IsQueueEnabled() const { |  | 
|  363   return main_thread_only().is_enabled; |  | 
|  364 } |  | 
|  365  |  | 
|  366 bool TaskQueueImpl::IsEmpty() const { |  349 bool TaskQueueImpl::IsEmpty() const { | 
|  367   if (!main_thread_only().delayed_work_queue->Empty() || |  350   if (!main_thread_only().delayed_work_queue->Empty() || | 
|  368       !main_thread_only().delayed_incoming_queue.empty() || |  351       !main_thread_only().delayed_incoming_queue.empty() || | 
|  369       !main_thread_only().immediate_work_queue->Empty()) { |  352       !main_thread_only().immediate_work_queue->Empty()) { | 
|  370     return false; |  353     return false; | 
|  371   } |  354   } | 
|  372  |  355  | 
|  373   base::AutoLock lock(any_thread_lock_); |  356   base::AutoLock lock(any_thread_lock_); | 
|  374   return any_thread().immediate_incoming_queue.empty(); |  357   return any_thread().immediate_incoming_queue.empty(); | 
|  375 } |  358 } | 
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  499 } |  482 } | 
|  500  |  483  | 
|  501 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |  484 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { | 
|  502   base::AutoLock lock(any_thread_lock_); |  485   base::AutoLock lock(any_thread_lock_); | 
|  503   state->BeginDictionary(); |  486   state->BeginDictionary(); | 
|  504   state->SetString("name", GetName()); |  487   state->SetString("name", GetName()); | 
|  505   state->SetString( |  488   state->SetString( | 
|  506       "task_queue_id", |  489       "task_queue_id", | 
|  507       base::StringPrintf("%" PRIx64, static_cast<uint64_t>( |  490       base::StringPrintf("%" PRIx64, static_cast<uint64_t>( | 
|  508                                          reinterpret_cast<uintptr_t>(this)))); |  491                                          reinterpret_cast<uintptr_t>(this)))); | 
|  509   state->SetBoolean("enabled", main_thread_only().is_enabled); |  492   state->SetBoolean("enabled", IsQueueEnabled()); | 
|  510   state->SetString("time_domain_name", |  493   state->SetString("time_domain_name", | 
|  511                    main_thread_only().time_domain->GetName()); |  494                    main_thread_only().time_domain->GetName()); | 
|  512   bool verbose_tracing_enabled = false; |  495   bool verbose_tracing_enabled = false; | 
|  513   TRACE_EVENT_CATEGORY_GROUP_ENABLED( |  496   TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 
|  514       disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); |  497       disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); | 
|  515   state->SetInteger("immediate_incoming_queue_size", |  498   state->SetInteger("immediate_incoming_queue_size", | 
|  516                     any_thread().immediate_incoming_queue.size()); |  499                     any_thread().immediate_incoming_queue.size()); | 
|  517   state->SetInteger("delayed_incoming_queue_size", |  500   state->SetInteger("delayed_incoming_queue_size", | 
|  518                     main_thread_only().delayed_incoming_queue.size()); |  501                     main_thread_only().delayed_incoming_queue.size()); | 
|  519   state->SetInteger("immediate_work_queue_size", |  502   state->SetInteger("immediate_work_queue_size", | 
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  633     base::AutoLock lock(any_thread_lock_); |  616     base::AutoLock lock(any_thread_lock_); | 
|  634     if (!any_thread().immediate_incoming_queue.empty() && |  617     if (!any_thread().immediate_incoming_queue.empty() && | 
|  635         any_thread().immediate_incoming_queue.front().enqueue_order() > |  618         any_thread().immediate_incoming_queue.front().enqueue_order() > | 
|  636             previous_fence && |  619             previous_fence && | 
|  637         any_thread().immediate_incoming_queue.front().enqueue_order() < |  620         any_thread().immediate_incoming_queue.front().enqueue_order() < | 
|  638             main_thread_only().current_fence) { |  621             main_thread_only().current_fence) { | 
|  639       task_unblocked = true; |  622       task_unblocked = true; | 
|  640     } |  623     } | 
|  641   } |  624   } | 
|  642  |  625  | 
|  643   if (main_thread_only().is_enabled && task_unblocked) { |  626   if (IsQueueEnabled() && task_unblocked) { | 
|  644     main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |  627     main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 
|  645         FROM_HERE); |  628         FROM_HERE); | 
|  646   } |  629   } | 
|  647 } |  630 } | 
|  648  |  631  | 
|  649 void TaskQueueImpl::RemoveFence() { |  632 void TaskQueueImpl::RemoveFence() { | 
|  650   if (!main_thread_only().task_queue_manager) |  633   if (!main_thread_only().task_queue_manager) | 
|  651     return; |  634     return; | 
|  652  |  635  | 
|  653   EnqueueOrder previous_fence = main_thread_only().current_fence; |  636   EnqueueOrder previous_fence = main_thread_only().current_fence; | 
|  654   main_thread_only().current_fence = 0; |  637   main_thread_only().current_fence = 0; | 
|  655  |  638  | 
|  656   bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |  639   bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); | 
|  657   task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |  640   task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); | 
|  658  |  641  | 
|  659   if (!task_unblocked && previous_fence) { |  642   if (!task_unblocked && previous_fence) { | 
|  660     base::AutoLock lock(any_thread_lock_); |  643     base::AutoLock lock(any_thread_lock_); | 
|  661     if (!any_thread().immediate_incoming_queue.empty() && |  644     if (!any_thread().immediate_incoming_queue.empty() && | 
|  662         any_thread().immediate_incoming_queue.front().enqueue_order() > |  645         any_thread().immediate_incoming_queue.front().enqueue_order() > | 
|  663             previous_fence) { |  646             previous_fence) { | 
|  664       task_unblocked = true; |  647       task_unblocked = true; | 
|  665     } |  648     } | 
|  666   } |  649   } | 
|  667  |  650  | 
|  668   if (main_thread_only().is_enabled && task_unblocked) { |  651   if (IsQueueEnabled() && task_unblocked) { | 
|  669     main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |  652     main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 
|  670         FROM_HERE); |  653         FROM_HERE); | 
|  671   } |  654   } | 
|  672 } |  655 } | 
|  673  |  656  | 
|  674 bool TaskQueueImpl::BlockedByFence() const { |  657 bool TaskQueueImpl::BlockedByFence() const { | 
|  675   if (!main_thread_only().current_fence) |  658   if (!main_thread_only().current_fence) | 
|  676     return false; |  659     return false; | 
|  677  |  660  | 
|  678   if (!main_thread_only().immediate_work_queue->BlockedByFence() || |  661   if (!main_thread_only().immediate_work_queue->BlockedByFence() || | 
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  753   state->SetInteger("sequence_num", task.sequence_num); |  736   state->SetInteger("sequence_num", task.sequence_num); | 
|  754   state->SetBoolean("nestable", task.nestable); |  737   state->SetBoolean("nestable", task.nestable); | 
|  755   state->SetBoolean("is_high_res", task.is_high_res); |  738   state->SetBoolean("is_high_res", task.is_high_res); | 
|  756   state->SetBoolean("is_cancelled", task.task.IsCancelled()); |  739   state->SetBoolean("is_cancelled", task.task.IsCancelled()); | 
|  757   state->SetDouble( |  740   state->SetDouble( | 
|  758       "delayed_run_time", |  741       "delayed_run_time", | 
|  759       (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |  742       (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 
|  760   state->EndDictionary(); |  743   state->EndDictionary(); | 
|  761 } |  744 } | 
|  762  |  745  | 
 |  746 TaskQueueImpl::QueueEnabledVoterImpl::QueueEnabledVoterImpl( | 
 |  747     TaskQueueImpl* task_queue) | 
 |  748     : task_queue_(task_queue), enabled_(true) {} | 
 |  749  | 
 |  750 TaskQueueImpl::QueueEnabledVoterImpl::~QueueEnabledVoterImpl() { | 
 |  751   task_queue_->RemoveQueueEnabledVoter(this); | 
 |  752 } | 
 |  753  | 
 |  754 TaskQueue* TaskQueueImpl::QueueEnabledVoterImpl::GetTaskQueue() const { | 
 |  755   return task_queue_.get(); | 
 |  756 } | 
 |  757  | 
 |  758 void TaskQueueImpl::QueueEnabledVoterImpl::SetQueueEnabled(bool enabled) { | 
 |  759   if (enabled_ == enabled) | 
 |  760     return; | 
 |  761  | 
 |  762   task_queue_->QueueEnabledVoteChanged(enabled); | 
 |  763   enabled_ = enabled; | 
 |  764 } | 
 |  765  | 
 |  766 void TaskQueueImpl::RemoveQueueEnabledVoter( | 
 |  767     const QueueEnabledVoterImpl* voter) { | 
 |  768   bool was_enabled = IsQueueEnabled(); | 
 |  769   if (voter->enabled_) { | 
 |  770     main_thread_only().is_enabled_refcount--; | 
 |  771     DCHECK_GE(main_thread_only().is_enabled_refcount, 0); | 
 |  772   } | 
 |  773  | 
 |  774   main_thread_only().voter_refcount--; | 
 |  775   DCHECK_GE(main_thread_only().voter_refcount, 0); | 
 |  776  | 
 |  777   bool is_enabled = IsQueueEnabled(); | 
 |  778   if (was_enabled != is_enabled) | 
 |  779     EnableOrDisableWithSelector(is_enabled); | 
 |  780 } | 
 |  781  | 
 |  782 bool TaskQueueImpl::IsQueueEnabled() const { | 
 |  783   return main_thread_only().is_enabled_refcount == | 
 |  784          main_thread_only().voter_refcount; | 
 |  785 } | 
 |  786  | 
 |  787 void TaskQueueImpl::QueueEnabledVoteChanged(bool enabled) { | 
 |  788   bool was_enabled = IsQueueEnabled(); | 
 |  789   if (enabled) { | 
 |  790     main_thread_only().is_enabled_refcount++; | 
 |  791     DCHECK_LE(main_thread_only().is_enabled_refcount, | 
 |  792               main_thread_only().voter_refcount); | 
 |  793   } else { | 
 |  794     main_thread_only().is_enabled_refcount--; | 
 |  795     DCHECK_GE(main_thread_only().is_enabled_refcount, 0); | 
 |  796   } | 
 |  797  | 
 |  798   bool is_enabled = IsQueueEnabled(); | 
 |  799   if (was_enabled != is_enabled) | 
 |  800     EnableOrDisableWithSelector(is_enabled); | 
 |  801 } | 
 |  802  | 
 |  803 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { | 
 |  804   if (!main_thread_only().task_queue_manager) | 
 |  805     return; | 
 |  806  | 
 |  807   if (enable) { | 
 |  808     // Note it's the job of the selector to tell the TaskQueueManager if | 
 |  809     // a DoWork needs posting. | 
 |  810     main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 
 |  811   } else { | 
 |  812     main_thread_only().task_queue_manager->selector_.DisableQueue(this); | 
 |  813   } | 
 |  814 } | 
 |  815  | 
 |  816 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter> | 
 |  817 TaskQueueImpl::GetQueueEnabledVoter() { | 
 |  818   main_thread_only().voter_refcount++; | 
 |  819   main_thread_only().is_enabled_refcount++; | 
 |  820   return base::MakeUnique<QueueEnabledVoterImpl>(this); | 
 |  821 } | 
 |  822  | 
|  763 }  // namespace internal |  823 }  // namespace internal | 
|  764 }  // namespace scheduler |  824 }  // namespace scheduler | 
|  765 }  // namespace blink |  825 }  // namespace blink | 
| OLD | NEW |