LCOV - code coverage report
Current view: top level - src - cancelable-task.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 54 55 98.2 %
Date: 2019-04-17 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     3838237 : 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     1919016 :   if (TryRun(&previous) || previous == kRunning) {
      19     1720626 :     parent_->RemoveFinishedTask(id_);
      20             :   }
      21     1919221 : }
      22             : 
      23      188537 : CancelableTaskManager::CancelableTaskManager()
      24      377074 :     : task_id_counter_(kInvalidTaskId), canceled_(false) {}
      25             : 
      26      562056 : 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      187351 :   CHECK(canceled_);
      32      187354 : }
      33             : 
      34     1922158 : CancelableTaskManager::Id CancelableTaskManager::Register(Cancelable* task) {
      35     1922158 :   base::MutexGuard guard(&mutex_);
      36     1922162 :   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           0 :     return kInvalidTaskId;
      41             :   }
      42     1922162 :   CancelableTaskManager::Id id = ++task_id_counter_;
      43             :   // Id overflows are not supported.
      44     1922162 :   CHECK_NE(kInvalidTaskId, id);
      45     1922162 :   CHECK(!canceled_);
      46     1922162 :   cancelable_tasks_[id] = task;
      47     1922162 :   return id;
      48             : }
      49             : 
      50     1719952 : void CancelableTaskManager::RemoveFinishedTask(CancelableTaskManager::Id id) {
      51     1719952 :   CHECK_NE(kInvalidTaskId, id);
      52     1719952 :   base::MutexGuard guard(&mutex_);
      53             :   size_t removed = cancelable_tasks_.erase(id);
      54             :   USE(removed);
      55             :   DCHECK_NE(0u, removed);
      56     1720949 :   cancelable_tasks_barrier_.NotifyOne();
      57     1720836 : }
      58             : 
      59     1065281 : TryAbortResult CancelableTaskManager::TryAbort(CancelableTaskManager::Id id) {
      60     1065281 :   CHECK_NE(kInvalidTaskId, id);
      61     1065281 :   base::MutexGuard guard(&mutex_);
      62             :   auto entry = cancelable_tasks_.find(id);
      63     1065281 :   if (entry != cancelable_tasks_.end()) {
      64      542652 :     Cancelable* value = entry->second;
      65      542652 :     if (value->Cancel()) {
      66             :       // Cannot call RemoveFinishedTask here because of recursive locking.
      67             :       cancelable_tasks_.erase(entry);
      68      177201 :       cancelable_tasks_barrier_.NotifyOne();
      69      177201 :       return TryAbortResult::kTaskAborted;
      70             :     } else {
      71             :       return TryAbortResult::kTaskRunning;
      72             :     }
      73             :   }
      74             :   return TryAbortResult::kTaskRemoved;
      75             : }
      76             : 
      77      189941 : 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      189941 :   base::MutexGuard guard(&mutex_);
      83      189939 :   canceled_ = true;
      84             : 
      85             :   // Cancelable tasks could be running or could potentially register new
      86             :   // tasks, requiring a loop here.
      87      200930 :   while (!cancelable_tasks_.empty()) {
      88       43957 :     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       65932 :       if (current->second->Cancel()) {
      93             :         cancelable_tasks_.erase(current);
      94             :       }
      95             :     }
      96             :     // Wait for already running background tasks.
      97       10991 :     if (!cancelable_tasks_.empty()) {
      98        3836 :       cancelable_tasks_barrier_.Wait(&mutex_);
      99             :     }
     100             :   }
     101      189940 : }
     102             : 
     103       62423 : 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       62423 :   base::MutexGuard guard(&mutex_);
     107             : 
     108       62423 :   if (cancelable_tasks_.empty()) return TryAbortResult::kTaskRemoved;
     109             : 
     110          25 :   for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
     111          34 :     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           8 :                                    : TryAbortResult::kTaskRunning;
     120             : }
     121             : 
     122     1699563 : CancelableTask::CancelableTask(Isolate* isolate)
     123     1699563 :     : CancelableTask(isolate->cancelable_task_manager()) {}
     124             : 
     125      218837 : CancelableTask::CancelableTask(CancelableTaskManager* manager)
     126     3836804 :     : Cancelable(manager) {}
     127             : 
     128        3730 : CancelableIdleTask::CancelableIdleTask(Isolate* isolate)
     129        3730 :     : CancelableIdleTask(isolate->cancelable_task_manager()) {}
     130             : 
     131          16 : CancelableIdleTask::CancelableIdleTask(CancelableTaskManager* manager)
     132        7492 :     : Cancelable(manager) {}
     133             : 
     134             : }  // namespace internal
     135      121996 : }  // namespace v8

Generated by: LCOV version 1.10