LCOV - code coverage report
Current view: top level - src - cancelable-task.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 55 55 100.0 %
Date: 2019-01-20 Functions: 14 15 93.3 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/cancelable-task.h"
       6             : 
       7             : #include "src/base/platform/platform.h"
       8             : #include "src/isolate.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : 
      13     1813308 : Cancelable::~Cancelable() {
      14             :   // The following check is needed to avoid calling an already terminated
      15             :   // manager object. This happens when the manager cancels all pending tasks
      16             :   // in {CancelAndWait} only before destroying the manager object.
      17             :   Status previous;
      18     1814543 :   if (TryRun(&previous) || previous == kRunning) {
      19     1639977 :     parent_->RemoveFinishedTask(id_);
      20             :   }
      21     1814838 : }
      22             : 
      23     3189655 : CancelableTaskManager::CancelableTaskManager()
      24     6379310 :     : task_id_counter_(kInvalidTaskId), canceled_(false) {}
      25             : 
      26     6379244 : CancelableTaskManager::~CancelableTaskManager() {
      27             :   // It is required that {CancelAndWait} is called before the manager object is
      28             :   // destroyed. This guarantees that all tasks managed by this
      29             :   // {CancelableTaskManager} are either canceled or finished their execution
      30             :   // when the {CancelableTaskManager} dies.
      31     3189622 :   CHECK(canceled_);
      32     3189625 : }
      33             : 
      34     1815326 : CancelableTaskManager::Id CancelableTaskManager::Register(Cancelable* task) {
      35     1815326 :   base::MutexGuard guard(&mutex_);
      36     1815328 :   if (canceled_) {
      37             :     // The CancelableTaskManager has already been canceled. Therefore we mark
      38             :     // the new task immediately as canceled so that it does not get executed.
      39             :     task->Cancel();
      40           5 :     return kInvalidTaskId;
      41             :   }
      42     1815323 :   CancelableTaskManager::Id id = ++task_id_counter_;
      43             :   // Id overflows are not supported.
      44     1815323 :   CHECK_NE(kInvalidTaskId, id);
      45     1815323 :   CHECK(!canceled_);
      46     1815324 :   cancelable_tasks_[id] = task;
      47     1815324 :   return id;
      48             : }
      49             : 
      50     1639647 : void CancelableTaskManager::RemoveFinishedTask(CancelableTaskManager::Id id) {
      51     1639647 :   CHECK_NE(kInvalidTaskId, id);
      52     1639647 :   base::MutexGuard guard(&mutex_);
      53             :   size_t removed = cancelable_tasks_.erase(id);
      54             :   USE(removed);
      55             :   DCHECK_NE(0u, removed);
      56     1640328 :   cancelable_tasks_barrier_.NotifyOne();
      57     1640273 : }
      58             : 
      59     1101732 : TryAbortResult CancelableTaskManager::TryAbort(CancelableTaskManager::Id id) {
      60     1101732 :   CHECK_NE(kInvalidTaskId, id);
      61     1101732 :   base::MutexGuard guard(&mutex_);
      62             :   auto entry = cancelable_tasks_.find(id);
      63     1101732 :   if (entry != cancelable_tasks_.end()) {
      64      550219 :     Cancelable* value = entry->second;
      65      550219 :     if (value->Cancel()) {
      66             :       // Cannot call RemoveFinishedTask here because of recursive locking.
      67             :       cancelable_tasks_.erase(entry);
      68      160215 :       cancelable_tasks_barrier_.NotifyOne();
      69      160215 :       return TryAbortResult::kTaskAborted;
      70             :     } else {
      71             :       return TryAbortResult::kTaskRunning;
      72             :     }
      73             :   }
      74             :   return TryAbortResult::kTaskRemoved;
      75             : }
      76             : 
      77     3192484 : void CancelableTaskManager::CancelAndWait() {
      78             :   // Clean up all cancelable fore- and background tasks. Tasks are canceled on
      79             :   // the way if possible, i.e., if they have not started yet.  After each round
      80             :   // of canceling we wait for the background tasks that have already been
      81             :   // started.
      82     3192484 :   base::MutexGuard guard(&mutex_);
      83     3192485 :   canceled_ = true;
      84             : 
      85             :   // Cancelable tasks could be running or could potentially register new
      86             :   // tasks, requiring a loop here.
      87     6398122 :   while (!cancelable_tasks_.empty()) {
      88       41495 :     for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
      89             :       auto current = it;
      90             :       // We need to get to the next element before erasing the current.
      91             :       ++it;
      92       30382 :       if (current->second->Cancel()) {
      93             :         cancelable_tasks_.erase(current);
      94             :       }
      95             :     }
      96             :     // Wait for already running background tasks.
      97       13152 :     if (!cancelable_tasks_.empty()) {
      98         300 :       cancelable_tasks_barrier_.Wait(&mutex_);
      99             :     }
     100             :   }
     101     3192485 : }
     102             : 
     103       62882 : TryAbortResult CancelableTaskManager::TryAbortAll() {
     104             :   // Clean up all cancelable fore- and background tasks. Tasks are canceled on
     105             :   // the way if possible, i.e., if they have not started yet.
     106       62882 :   base::MutexGuard guard(&mutex_);
     107             : 
     108       62884 :   if (cancelable_tasks_.empty()) return TryAbortResult::kTaskRemoved;
     109             : 
     110          36 :   for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
     111          44 :     if (it->second->Cancel()) {
     112             :       it = cancelable_tasks_.erase(it);
     113             :     } else {
     114             :       ++it;
     115             :     }
     116             :   }
     117             : 
     118             :   return cancelable_tasks_.empty() ? TryAbortResult::kTaskAborted
     119           7 :                                    : TryAbortResult::kTaskRunning;
     120             : }
     121             : 
     122     1751715 : CancelableTask::CancelableTask(Isolate* isolate)
     123     1751715 :     : CancelableTask(isolate->cancelable_task_manager()) {}
     124             : 
     125       59724 : CancelableTask::CancelableTask(CancelableTaskManager* manager)
     126     3622880 :     : Cancelable(manager) {}
     127             : 
     128        3859 : CancelableIdleTask::CancelableIdleTask(Isolate* isolate)
     129        3859 :     : CancelableIdleTask(isolate->cancelable_task_manager()) {}
     130             : 
     131          16 : CancelableIdleTask::CancelableIdleTask(CancelableTaskManager* manager)
     132        7750 :     : Cancelable(manager) {}
     133             : 
     134             : }  // namespace internal
     135      183867 : }  // namespace v8

Generated by: LCOV version 1.10