LCOV - code coverage report
Current view: top level - src - cancelable-task.h (source / functions) Hit Total Coverage
Test: app.info Lines: 16 16 100.0 %
Date: 2017-10-20 Functions: 6 10 60.0 %

          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             : #ifndef V8_CANCELABLE_TASK_H_
       6             : #define V8_CANCELABLE_TASK_H_
       7             : 
       8             : #include <unordered_map>
       9             : 
      10             : #include "include/v8-platform.h"
      11             : #include "src/base/atomic-utils.h"
      12             : #include "src/base/macros.h"
      13             : #include "src/base/platform/condition-variable.h"
      14             : #include "src/globals.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19             : class Cancelable;
      20             : class Isolate;
      21             : 
      22             : 
      23             : // Keeps track of cancelable tasks. It is possible to register and remove tasks
      24             : // from any fore- and background task/thread.
      25      521966 : class V8_EXPORT_PRIVATE CancelableTaskManager {
      26             :  public:
      27             :   using Id = uint64_t;
      28             : 
      29             :   CancelableTaskManager();
      30             : 
      31             :   // Registers a new cancelable {task}. Returns the unique {id} of the task that
      32             :   // can be used to try to abort a task by calling {Abort}.
      33             :   // Must not be called after CancelAndWait.
      34             :   Id Register(Cancelable* task);
      35             : 
      36             :   // Try to abort running a task identified by {id}. The possible outcomes are:
      37             :   // (1) The task is already finished running or was canceled before and
      38             :   //     thus has been removed from the manager.
      39             :   // (2) The task is currently running and cannot be canceled anymore.
      40             :   // (3) The task is not yet running (or finished) so it is canceled and
      41             :   //     removed.
      42             :   //
      43             :   enum TryAbortResult { kTaskRemoved, kTaskRunning, kTaskAborted };
      44             :   TryAbortResult TryAbort(Id id);
      45             : 
      46             :   // Cancels all remaining registered tasks and waits for tasks that are
      47             :   // already running. This disallows subsequent Register calls.
      48             :   void CancelAndWait();
      49             : 
      50             :   // Tries to cancel all remaining registered tasks. The return value indicates
      51             :   // whether
      52             :   //
      53             :   // 1) No tasks were registered (kTaskRemoved), or
      54             :   //
      55             :   // 2) There is at least one remaining task that couldn't be cancelled
      56             :   // (kTaskRunning), or
      57             :   //
      58             :   // 3) All registered tasks were cancelled (kTaskAborted).
      59             :   TryAbortResult TryAbortAll();
      60             : 
      61             :  private:
      62             :   // Only called by {Cancelable} destructor. The task is done with executing,
      63             :   // but needs to be removed.
      64             :   void RemoveFinishedTask(Id id);
      65             : 
      66             :   // To mitigate the ABA problem, the api refers to tasks through an id.
      67             :   Id task_id_counter_;
      68             : 
      69             :   // A set of cancelable tasks that are currently registered.
      70             :   std::unordered_map<Id, Cancelable*> cancelable_tasks_;
      71             : 
      72             :   // Mutex and condition variable enabling concurrent register and removing, as
      73             :   // well as waiting for background tasks on {CancelAndWait}.
      74             :   base::ConditionVariable cancelable_tasks_barrier_;
      75             :   base::Mutex mutex_;
      76             : 
      77             :   bool canceled_;
      78             : 
      79             :   friend class Cancelable;
      80             : 
      81             :   DISALLOW_COPY_AND_ASSIGN(CancelableTaskManager);
      82             : };
      83             : 
      84             : class V8_EXPORT_PRIVATE Cancelable {
      85             :  public:
      86             :   explicit Cancelable(CancelableTaskManager* parent);
      87             :   virtual ~Cancelable();
      88             : 
      89             :   // Never invoke after handing over the task to the platform! The reason is
      90             :   // that {Cancelable} is used in combination with {v8::Task} and handed to
      91             :   // a platform. This step transfers ownership to the platform, which destroys
      92             :   // the task after running it. Since the exact time is not known, we cannot
      93             :   // access the object after handing it to a platform.
      94             :   CancelableTaskManager::Id id() { return id_; }
      95             : 
      96             :  protected:
      97     4179407 :   bool TryRun() { return status_.TrySetValue(kWaiting, kRunning); }
      98     2092122 :   bool IsRunning() { return status_.Value() == kRunning; }
      99             :   intptr_t CancelAttempts() { return cancel_counter_.Value(); }
     100             : 
     101             :  private:
     102             :   // Identifies the state a cancelable task is in:
     103             :   // |kWaiting|: The task is scheduled and waiting to be executed. {TryRun} will
     104             :   //   succeed.
     105             :   // |kCanceled|: The task has been canceled. {TryRun} will fail.
     106             :   // |kRunning|: The task is currently running and cannot be canceled anymore.
     107             :   enum Status {
     108             :     kWaiting,
     109             :     kCanceled,
     110             :     kRunning,
     111             :   };
     112             : 
     113             :   // Use {CancelableTaskManager} to abort a task that has not yet been
     114             :   // executed.
     115       84415 :   bool Cancel() {
     116       84415 :     if (status_.TrySetValue(kWaiting, kCanceled)) {
     117             :       return true;
     118             :     }
     119             :     cancel_counter_.Increment(1);
     120       44264 :     return false;
     121             :   }
     122             : 
     123             :   CancelableTaskManager* parent_;
     124             :   base::AtomicValue<Status> status_;
     125             :   CancelableTaskManager::Id id_;
     126             : 
     127             :   // The counter is incremented for failing tries to cancel a task. This can be
     128             :   // used by the task itself as an indication how often external entities tried
     129             :   // to abort it.
     130             :   base::AtomicNumber<intptr_t> cancel_counter_;
     131             : 
     132             :   friend class CancelableTaskManager;
     133             : 
     134             :   DISALLOW_COPY_AND_ASSIGN(Cancelable);
     135             : };
     136             : 
     137             : 
     138             : // Multiple inheritance can be used because Task is a pure interface.
     139     2078572 : class V8_EXPORT_PRIVATE CancelableTask : public Cancelable,
     140             :                                          NON_EXPORTED_BASE(public Task) {
     141             :  public:
     142             :   explicit CancelableTask(Isolate* isolate);
     143             :   explicit CancelableTask(CancelableTaskManager* manager);
     144             : 
     145             :   // Task overrides.
     146     1039306 :   void Run() final {
     147     1039306 :     if (TryRun()) {
     148     1000275 :       RunInternal();
     149             :     }
     150     1039603 :   }
     151             : 
     152             :   virtual void RunInternal() = 0;
     153             : 
     154             :  private:
     155             :   DISALLOW_COPY_AND_ASSIGN(CancelableTask);
     156             : };
     157             : 
     158             : 
     159             : // Multiple inheritance can be used because IdleTask is a pure interface.
     160       11232 : class CancelableIdleTask : public Cancelable, public IdleTask {
     161             :  public:
     162             :   explicit CancelableIdleTask(Isolate* isolate);
     163             :   explicit CancelableIdleTask(CancelableTaskManager* manager);
     164             : 
     165             :   // IdleTask overrides.
     166        5603 :   void Run(double deadline_in_seconds) final {
     167        5603 :     if (TryRun()) {
     168        5603 :       RunInternal(deadline_in_seconds);
     169             :     }
     170        5603 :   }
     171             : 
     172             :   virtual void RunInternal(double deadline_in_seconds) = 0;
     173             : 
     174             :  private:
     175             :   DISALLOW_COPY_AND_ASSIGN(CancelableIdleTask);
     176             : };
     177             : 
     178             : 
     179             : }  // namespace internal
     180             : }  // namespace v8
     181             : 
     182             : #endif  // V8_CANCELABLE_TASK_H_

Generated by: LCOV version 1.10