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-04-26 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      783190 :     : parent_(parent), status_(kWaiting), id_(0), cancel_counter_(0) {
      16      391595 :   id_ = parent->Register(this);
      17          13 : }
      18             : 
      19             : 
      20      391443 : 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      391443 :   if (TryRun() || IsRunning()) {
      25      387829 :     parent_->RemoveFinishedTask(id_);
      26             :   }
      27      391541 : }
      28             : 
      29      121600 : CancelableTaskManager::CancelableTaskManager()
      30      243200 :     : task_id_counter_(0), canceled_(false) {}
      31             : 
      32      391595 : uint32_t CancelableTaskManager::Register(Cancelable* task) {
      33      391595 :   base::LockGuard<base::Mutex> guard(&mutex_);
      34      391595 :   uint32_t id = ++task_id_counter_;
      35             :   // The loop below is just used when task_id_counter_ overflows.
      36      783190 :   while (cancelable_tasks_.count(id) > 0) ++id;
      37      391595 :   CHECK(!canceled_);
      38      391595 :   cancelable_tasks_[id] = task;
      39      783190 :   return id;
      40             : }
      41             : 
      42             : 
      43      387811 : void CancelableTaskManager::RemoveFinishedTask(uint32_t id) {
      44      387811 :   base::LockGuard<base::Mutex> guard(&mutex_);
      45             :   size_t removed = cancelable_tasks_.erase(id);
      46             :   USE(removed);
      47             :   DCHECK_NE(0u, removed);
      48      387876 :   cancelable_tasks_barrier_.NotifyOne();
      49      387875 : }
      50             : 
      51      203769 : CancelableTaskManager::TryAbortResult CancelableTaskManager::TryAbort(
      52             :     uint32_t id) {
      53      203769 :   base::LockGuard<base::Mutex> guard(&mutex_);
      54             :   auto entry = cancelable_tasks_.find(id);
      55      203769 :   if (entry != cancelable_tasks_.end()) {
      56        6929 :     Cancelable* value = entry->second;
      57        6929 :     if (value->Cancel()) {
      58             :       // Cannot call RemoveFinishedTask here because of recursive locking.
      59             :       cancelable_tasks_.erase(entry);
      60        3247 :       cancelable_tasks_barrier_.NotifyOne();
      61        3247 :       return kTaskAborted;
      62             :     } else {
      63             :       return kTaskRunning;
      64             :     }
      65             :   }
      66             :   return kTaskRemoved;
      67             : }
      68             : 
      69             : 
      70      118610 : void CancelableTaskManager::CancelAndWait() {
      71             :   // Clean up all cancelable fore- and background tasks. Tasks are canceled on
      72             :   // the way if possible, i.e., if they have not started yet.  After each round
      73             :   // of canceling we wait for the background tasks that have already been
      74             :   // started.
      75      118610 :   base::LockGuard<base::Mutex> guard(&mutex_);
      76      118610 :   canceled_ = true;
      77             : 
      78             :   // Cancelable tasks could be running or could potentially register new
      79             :   // tasks, requiring a loop here.
      80      237638 :   while (!cancelable_tasks_.empty()) {
      81        1263 :     for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
      82             :       auto current = it;
      83             :       // We need to get to the next element before erasing the current.
      84             :       ++it;
      85         427 :       if (current->second->Cancel()) {
      86             :         cancelable_tasks_.erase(current);
      87             :       }
      88             :     }
      89             :     // Wait for already running background tasks.
      90         418 :     if (!cancelable_tasks_.empty()) {
      91          11 :       cancelable_tasks_barrier_.Wait(&mutex_);
      92             :     }
      93             :   }
      94      118610 : }
      95             : 
      96      118613 : CancelableTaskManager::TryAbortResult CancelableTaskManager::TryAbortAll() {
      97             :   // Clean up all cancelable fore- and background tasks. Tasks are canceled on
      98             :   // the way if possible, i.e., if they have not started yet.
      99      118613 :   base::LockGuard<base::Mutex> guard(&mutex_);
     100             : 
     101      118613 :   if (cancelable_tasks_.empty()) return kTaskRemoved;
     102             : 
     103          54 :   for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
     104          20 :     if (it->second->Cancel()) {
     105             :       it = cancelable_tasks_.erase(it);
     106             :     } else {
     107             :       ++it;
     108             :     }
     109             :   }
     110             : 
     111          17 :   return cancelable_tasks_.empty() ? kTaskAborted : kTaskRunning;
     112             : }
     113             : 
     114      382396 : CancelableTask::CancelableTask(Isolate* isolate)
     115      382396 :     : CancelableTask(isolate, isolate->cancelable_task_manager()) {}
     116             : 
     117          30 : CancelableTask::CancelableTask(Isolate* isolate, CancelableTaskManager* manager)
     118      764852 :     : Cancelable(manager), isolate_(isolate) {}
     119             : 
     120        9123 : CancelableIdleTask::CancelableIdleTask(Isolate* isolate)
     121        9123 :     : CancelableIdleTask(isolate, isolate->cancelable_task_manager()) {}
     122             : 
     123          33 : CancelableIdleTask::CancelableIdleTask(Isolate* isolate,
     124             :                                        CancelableTaskManager* manager)
     125       18312 :     : Cancelable(manager), isolate_(isolate) {}
     126             : 
     127             : }  // namespace internal
     128             : }  // namespace v8

Generated by: LCOV version 1.10