LCOV - code coverage report
Current view: top level - src - cancelable-task.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 51 51 100.0 %
Date: 2017-10-20 Functions: 12 13 92.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             : 
      14          13 : Cancelable::Cancelable(CancelableTaskManager* parent)
      15     2093344 :     : parent_(parent), status_(kWaiting), id_(0), cancel_counter_(0) {
      16     1046672 :   id_ = parent->Register(this);
      17          13 : }
      18             : 
      19             : 
      20     1044591 : Cancelable::~Cancelable() {
      21             :   // The following check is needed to avoid calling an already terminated
      22             :   // manager object. This happens when the manager cancels all pending tasks
      23             :   // in {CancelAndWait} only before destroying the manager object.
      24     1044591 :   if (TryRun() || IsRunning()) {
      25     1005900 :     parent_->RemoveFinishedTask(id_);
      26             :   }
      27     1046217 : }
      28             : 
      29      264251 : CancelableTaskManager::CancelableTaskManager()
      30      528502 :     : task_id_counter_(0), canceled_(false) {}
      31             : 
      32     1046672 : CancelableTaskManager::Id CancelableTaskManager::Register(Cancelable* task) {
      33     1046672 :   base::LockGuard<base::Mutex> guard(&mutex_);
      34     1046671 :   CancelableTaskManager::Id id = ++task_id_counter_;
      35             :   // Id overflows are not supported.
      36     1046671 :   CHECK_NE(0, id);
      37     1046671 :   CHECK(!canceled_);
      38     1046671 :   cancelable_tasks_[id] = task;
      39     2093343 :   return id;
      40             : }
      41             : 
      42     1005548 : void CancelableTaskManager::RemoveFinishedTask(CancelableTaskManager::Id id) {
      43     1005548 :   base::LockGuard<base::Mutex> guard(&mutex_);
      44             :   size_t removed = cancelable_tasks_.erase(id);
      45             :   USE(removed);
      46             :   DCHECK_NE(0u, removed);
      47     1006194 :   cancelable_tasks_barrier_.NotifyOne();
      48     1006159 : }
      49             : 
      50      581764 : CancelableTaskManager::TryAbortResult CancelableTaskManager::TryAbort(
      51             :     CancelableTaskManager::Id id) {
      52      581764 :   base::LockGuard<base::Mutex> guard(&mutex_);
      53             :   auto entry = cancelable_tasks_.find(id);
      54      581764 :   if (entry != cancelable_tasks_.end()) {
      55       74834 :     Cancelable* value = entry->second;
      56       74834 :     if (value->Cancel()) {
      57             :       // Cannot call RemoveFinishedTask here because of recursive locking.
      58             :       cancelable_tasks_.erase(entry);
      59       37094 :       cancelable_tasks_barrier_.NotifyOne();
      60       37094 :       return kTaskAborted;
      61             :     } else {
      62             :       return kTaskRunning;
      63             :     }
      64             :   }
      65             :   return kTaskRemoved;
      66             : }
      67             : 
      68             : 
      69      110952 : void CancelableTaskManager::CancelAndWait() {
      70             :   // Clean up all cancelable fore- and background tasks. Tasks are canceled on
      71             :   // the way if possible, i.e., if they have not started yet.  After each round
      72             :   // of canceling we wait for the background tasks that have already been
      73             :   // started.
      74      110952 :   base::LockGuard<base::Mutex> guard(&mutex_);
      75      110952 :   canceled_ = true;
      76             : 
      77             :   // Cancelable tasks could be running or could potentially register new
      78             :   // tasks, requiring a loop here.
      79      225609 :   while (!cancelable_tasks_.empty()) {
      80       16971 :     for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
      81             :       auto current = it;
      82             :       // We need to get to the next element before erasing the current.
      83             :       ++it;
      84        9561 :       if (current->second->Cancel()) {
      85             :         cancelable_tasks_.erase(current);
      86             :       }
      87             :     }
      88             :     // Wait for already running background tasks.
      89        3705 :     if (!cancelable_tasks_.empty()) {
      90        2370 :       cancelable_tasks_barrier_.Wait(&mutex_);
      91             :     }
      92             :   }
      93      110952 : }
      94             : 
      95      106767 : CancelableTaskManager::TryAbortResult CancelableTaskManager::TryAbortAll() {
      96             :   // Clean up all cancelable fore- and background tasks. Tasks are canceled on
      97             :   // the way if possible, i.e., if they have not started yet.
      98      106767 :   base::LockGuard<base::Mutex> guard(&mutex_);
      99             : 
     100      106767 :   if (cancelable_tasks_.empty()) return kTaskRemoved;
     101             : 
     102          54 :   for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
     103          20 :     if (it->second->Cancel()) {
     104             :       it = cancelable_tasks_.erase(it);
     105             :     } else {
     106             :       ++it;
     107             :     }
     108             :   }
     109             : 
     110          17 :   return cancelable_tasks_.empty() ? kTaskAborted : kTaskRunning;
     111             : }
     112             : 
     113     1016210 : CancelableTask::CancelableTask(Isolate* isolate)
     114     1016210 :     : CancelableTask(isolate->cancelable_task_manager()) {}
     115             : 
     116     1041043 : CancelableTask::CancelableTask(CancelableTaskManager* manager)
     117     2082086 :     : Cancelable(manager) {}
     118             : 
     119        5589 : CancelableIdleTask::CancelableIdleTask(Isolate* isolate)
     120        5589 :     : CancelableIdleTask(isolate->cancelable_task_manager()) {}
     121             : 
     122        5616 : CancelableIdleTask::CancelableIdleTask(CancelableTaskManager* manager)
     123       11232 :     : Cancelable(manager) {}
     124             : 
     125             : }  // namespace internal
     126             : }  // namespace v8

Generated by: LCOV version 1.10