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-03-21 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     3312082 : 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     1655938 :   if (TryRun(&previous) || previous == kRunning) {
      19     1466195 :     parent_->RemoveFinishedTask(id_);
      20             :   }
      21     1656144 : }
      22             : 
      23      185769 : CancelableTaskManager::CancelableTaskManager()
      24      371538 :     : task_id_counter_(kInvalidTaskId), canceled_(false) {}
      25             : 
      26      553760 : 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      184586 :   CHECK(canceled_);
      32      184588 : }
      33             : 
      34     1658766 : CancelableTaskManager::Id CancelableTaskManager::Register(Cancelable* task) {
      35     1658766 :   base::MutexGuard guard(&mutex_);
      36     1658768 :   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     1658762 :   CancelableTaskManager::Id id = ++task_id_counter_;
      43             :   // Id overflows are not supported.
      44     1658762 :   CHECK_NE(kInvalidTaskId, id);
      45     1658762 :   CHECK(!canceled_);
      46     1658760 :   cancelable_tasks_[id] = task;
      47     1658760 :   return id;
      48             : }
      49             : 
      50     1465451 : void CancelableTaskManager::RemoveFinishedTask(CancelableTaskManager::Id id) {
      51     1465451 :   CHECK_NE(kInvalidTaskId, id);
      52     1465451 :   base::MutexGuard guard(&mutex_);
      53             :   size_t removed = cancelable_tasks_.erase(id);
      54             :   USE(removed);
      55             :   DCHECK_NE(0u, removed);
      56     1466476 :   cancelable_tasks_barrier_.NotifyOne();
      57     1466410 : }
      58             : 
      59     1034597 : TryAbortResult CancelableTaskManager::TryAbort(CancelableTaskManager::Id id) {
      60     1034597 :   CHECK_NE(kInvalidTaskId, id);
      61     1034597 :   base::MutexGuard guard(&mutex_);
      62             :   auto entry = cancelable_tasks_.find(id);
      63     1034597 :   if (entry != cancelable_tasks_.end()) {
      64      548644 :     Cancelable* value = entry->second;
      65      548644 :     if (value->Cancel()) {
      66             :       // Cannot call RemoveFinishedTask here because of recursive locking.
      67             :       cancelable_tasks_.erase(entry);
      68      170246 :       cancelable_tasks_barrier_.NotifyOne();
      69      170246 :       return TryAbortResult::kTaskAborted;
      70             :     } else {
      71             :       return TryAbortResult::kTaskRunning;
      72             :     }
      73             :   }
      74             :   return TryAbortResult::kTaskRemoved;
      75             : }
      76             : 
      77      187100 : 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      187100 :   base::MutexGuard guard(&mutex_);
      83      187103 :   canceled_ = true;
      84             : 
      85             :   // Cancelable tasks could be running or could potentially register new
      86             :   // tasks, requiring a loop here.
      87      196007 :   while (!cancelable_tasks_.empty()) {
      88       37040 :     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       56272 :       if (current->second->Cancel()) {
      93             :         cancelable_tasks_.erase(current);
      94             :       }
      95             :     }
      96             :     // Wait for already running background tasks.
      97        8904 :     if (!cancelable_tasks_.empty()) {
      98        2886 :       cancelable_tasks_barrier_.Wait(&mutex_);
      99             :     }
     100             :   }
     101      187102 : }
     102             : 
     103       61534 : 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       61534 :   base::MutexGuard guard(&mutex_);
     107             : 
     108       61535 :   if (cancelable_tasks_.empty()) return TryAbortResult::kTaskRemoved;
     109             : 
     110          17 :   for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
     111          20 :     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     1616884 : CancelableTask::CancelableTask(Isolate* isolate)
     123     1616884 :     : CancelableTask(isolate->cancelable_task_manager()) {}
     124             : 
     125       38987 : CancelableTask::CancelableTask(CancelableTaskManager* manager)
     126     3311743 :     : Cancelable(manager) {}
     127             : 
     128        2863 : CancelableIdleTask::CancelableIdleTask(Isolate* isolate)
     129        2863 :     : CancelableIdleTask(isolate->cancelable_task_manager()) {}
     130             : 
     131          19 : CancelableIdleTask::CancelableIdleTask(CancelableTaskManager* manager)
     132        5764 :     : Cancelable(manager) {}
     133             : 
     134             : }  // namespace internal
     135      120216 : }  // namespace v8

Generated by: LCOV version 1.10