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-04-19 Functions: 13 14 92.9 %

          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     3792838 : 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     1896364 :   if (TryRun(&previous) || previous == kRunning) {
      19     1690790 :     parent_->RemoveFinishedTask(id_);
      20             :   }
      21     1896474 : }
      22             : 
      23      188614 : CancelableTaskManager::CancelableTaskManager()
      24      377228 :     : task_id_counter_(kInvalidTaskId), canceled_(false) {}
      25             : 
      26      562285 : 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      187428 :   CHECK(canceled_);
      32      187429 : }
      33             : 
      34     1899117 : CancelableTaskManager::Id CancelableTaskManager::Register(Cancelable* task) {
      35     1899117 :   base::MutexGuard guard(&mutex_);
      36     1899117 :   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           6 :     return kInvalidTaskId;
      41             :   }
      42     1899111 :   CancelableTaskManager::Id id = ++task_id_counter_;
      43             :   // Id overflows are not supported.
      44     1899111 :   CHECK_NE(kInvalidTaskId, id);
      45     1899111 :   CHECK(!canceled_);
      46     1899111 :   cancelable_tasks_[id] = task;
      47     1899111 :   return id;
      48             : }
      49             : 
      50     1690214 : void CancelableTaskManager::RemoveFinishedTask(CancelableTaskManager::Id id) {
      51     1690214 :   CHECK_NE(kInvalidTaskId, id);
      52     1690214 :   base::MutexGuard guard(&mutex_);
      53             :   size_t removed = cancelable_tasks_.erase(id);
      54             :   USE(removed);
      55             :   DCHECK_NE(0u, removed);
      56     1691034 :   cancelable_tasks_barrier_.NotifyOne();
      57     1690908 : }
      58             : 
      59     1062663 : TryAbortResult CancelableTaskManager::TryAbort(CancelableTaskManager::Id id) {
      60     1062663 :   CHECK_NE(kInvalidTaskId, id);
      61     1062663 :   base::MutexGuard guard(&mutex_);
      62             :   auto entry = cancelable_tasks_.find(id);
      63     1062663 :   if (entry != cancelable_tasks_.end()) {
      64      543217 :     Cancelable* value = entry->second;
      65      543217 :     if (value->Cancel()) {
      66             :       // Cannot call RemoveFinishedTask here because of recursive locking.
      67             :       cancelable_tasks_.erase(entry);
      68      182820 :       cancelable_tasks_barrier_.NotifyOne();
      69      182820 :       return TryAbortResult::kTaskAborted;
      70             :     } else {
      71             :       return TryAbortResult::kTaskRunning;
      72             :     }
      73             :   }
      74             :   return TryAbortResult::kTaskRemoved;
      75             : }
      76             : 
      77      190034 : 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      190034 :   base::MutexGuard guard(&mutex_);
      83      190035 :   canceled_ = true;
      84             : 
      85             :   // Cancelable tasks could be running or could potentially register new
      86             :   // tasks, requiring a loop here.
      87      201296 :   while (!cancelable_tasks_.empty()) {
      88       45633 :     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       68744 :       if (current->second->Cancel()) {
      93             :         cancelable_tasks_.erase(current);
      94             :       }
      95             :     }
      96             :     // Wait for already running background tasks.
      97       11261 :     if (!cancelable_tasks_.empty()) {
      98        4005 :       cancelable_tasks_barrier_.Wait(&mutex_);
      99             :     }
     100             :   }
     101      190035 : }
     102             : 
     103       62442 : 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       62442 :   base::MutexGuard guard(&mutex_);
     107             : 
     108       62443 :   if (cancelable_tasks_.empty()) return TryAbortResult::kTaskRemoved;
     109             : 
     110          21 :   for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
     111          30 :     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           6 :                                    : TryAbortResult::kTaskRunning;
     120             : }
     121             : 
     122     1673959 : CancelableTask::CancelableTask(Isolate* isolate)
     123     1673959 :     : CancelableTask(isolate->cancelable_task_manager()) {}
     124             : 
     125      221390 : CancelableTask::CancelableTask(CancelableTaskManager* manager)
     126     3790698 :     : Cancelable(manager) {}
     127             : 
     128        3739 : CancelableIdleTask::CancelableIdleTask(Isolate* isolate)
     129        3739 :     : CancelableIdleTask(isolate->cancelable_task_manager()) {}
     130             : 
     131          16 : CancelableIdleTask::CancelableIdleTask(CancelableTaskManager* manager)
     132        7510 :     : Cancelable(manager) {}
     133             : 
     134             : }  // namespace internal
     135      122036 : }  // namespace v8

Generated by: LCOV version 1.10