LCOV - code coverage report
Current view: top level - src - cancelable-task.h (source / functions) Hit Total Coverage
Test: app.info Lines: 12 12 100.0 %
Date: 2019-04-19 Functions: 2 2 100.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 <atomic>
       9             : #include <unordered_map>
      10             : 
      11             : #include "include/v8-platform.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             : // The possible outcomes of trying to abort a job are:
      23             : // (1) The task is already finished running or was canceled before and
      24             : //     thus has been removed from the manager.
      25             : // (2) The task is currently running and cannot be canceled anymore.
      26             : // (3) The task is not yet running (or finished) so it is canceled and
      27             : //     removed.
      28             : enum class TryAbortResult { kTaskRemoved, kTaskRunning, kTaskAborted };
      29             : 
      30             : // Keeps track of cancelable tasks. It is possible to register and remove tasks
      31             : // from any fore- and background task/thread.
      32             : class V8_EXPORT_PRIVATE CancelableTaskManager {
      33             :  public:
      34             :   using Id = uint64_t;
      35             : 
      36             :   CancelableTaskManager();
      37             : 
      38             :   ~CancelableTaskManager();
      39             : 
      40             :   // Registers a new cancelable {task}. Returns the unique {id} of the task that
      41             :   // can be used to try to abort a task by calling {Abort}.
      42             :   // If {Register} is called after {CancelAndWait}, then the task will be
      43             :   // aborted immediately.
      44             :   // {Register} should only be called by the thread which owns the
      45             :   // {CancelableTaskManager}, or by a task which is managed by the
      46             :   // {CancelableTaskManager}.
      47             :   Id Register(Cancelable* task);
      48             : 
      49             :   // Try to abort running a task identified by {id}.
      50             :   TryAbortResult TryAbort(Id id);
      51             : 
      52             :   // Tries to cancel all remaining registered tasks. The return value indicates
      53             :   // whether
      54             :   //
      55             :   // 1) No tasks were registered (kTaskRemoved), or
      56             :   //
      57             :   // 2) There is at least one remaining task that couldn't be cancelled
      58             :   // (kTaskRunning), or
      59             :   //
      60             :   // 3) All registered tasks were cancelled (kTaskAborted).
      61             :   TryAbortResult TryAbortAll();
      62             : 
      63             :   // Cancels all remaining registered tasks and waits for tasks that are
      64             :   // already running. This disallows subsequent Register calls.
      65             :   void CancelAndWait();
      66             : 
      67             :   // Returns true of the task manager has been cancelled.
      68             :   bool canceled() const { return canceled_; }
      69             : 
      70             :  private:
      71             :   static constexpr Id kInvalidTaskId = 0;
      72             : 
      73             :   // Only called by {Cancelable} destructor. The task is done with executing,
      74             :   // but needs to be removed.
      75             :   void RemoveFinishedTask(Id id);
      76             : 
      77             :   // To mitigate the ABA problem, the api refers to tasks through an id.
      78             :   Id task_id_counter_;
      79             : 
      80             :   // A set of cancelable tasks that are currently registered.
      81             :   std::unordered_map<Id, Cancelable*> cancelable_tasks_;
      82             : 
      83             :   // Mutex and condition variable enabling concurrent register and removing, as
      84             :   // well as waiting for background tasks on {CancelAndWait}.
      85             :   base::ConditionVariable cancelable_tasks_barrier_;
      86             :   base::Mutex mutex_;
      87             : 
      88             :   bool canceled_;
      89             : 
      90             :   friend class Cancelable;
      91             : 
      92             :   DISALLOW_COPY_AND_ASSIGN(CancelableTaskManager);
      93             : };
      94             : 
      95             : class V8_EXPORT_PRIVATE Cancelable {
      96             :  public:
      97             :   explicit Cancelable(CancelableTaskManager* parent)
      98     3798234 :       : parent_(parent), id_(parent->Register(this)) {}
      99             : 
     100             :   virtual ~Cancelable();
     101             : 
     102             :   // Never invoke after handing over the task to the platform! The reason is
     103             :   // that {Cancelable} is used in combination with {v8::Task} and handed to
     104             :   // a platform. This step transfers ownership to the platform, which destroys
     105             :   // the task after running it. Since the exact time is not known, we cannot
     106             :   // access the object after handing it to a platform.
     107             :   CancelableTaskManager::Id id() { return id_; }
     108             : 
     109             :  protected:
     110             :   // Identifies the state a cancelable task is in:
     111             :   // |kWaiting|: The task is scheduled and waiting to be executed. {TryRun} will
     112             :   //   succeed.
     113             :   // |kCanceled|: The task has been canceled. {TryRun} will fail.
     114             :   // |kRunning|: The task is currently running and cannot be canceled anymore.
     115             :   enum Status { kWaiting, kCanceled, kRunning };
     116             : 
     117             :   bool TryRun(Status* previous = nullptr) {
     118             :     return CompareExchangeStatus(kWaiting, kRunning, previous);
     119             :   }
     120             : 
     121             :  private:
     122             :   friend class CancelableTaskManager;
     123             : 
     124             :   // Use {CancelableTaskManager} to abort a task that has not yet been
     125             :   // executed.
     126             :   bool Cancel() { return CompareExchangeStatus(kWaiting, kCanceled); }
     127             : 
     128             :   bool CompareExchangeStatus(Status expected, Status desired,
     129             :                              Status* previous = nullptr) {
     130             :     // {compare_exchange_strong} updates {expected}.
     131             :     bool success = status_.compare_exchange_strong(expected, desired,
     132             :                                                    std::memory_order_acq_rel,
     133             :                                                    std::memory_order_acquire);
     134     1896364 :     if (previous) *previous = expected;
     135             :     return success;
     136             :   }
     137             : 
     138             :   CancelableTaskManager* const parent_;
     139             :   std::atomic<Status> status_{kWaiting};
     140             :   const CancelableTaskManager::Id id_;
     141             : 
     142             :   DISALLOW_COPY_AND_ASSIGN(Cancelable);
     143             : };
     144             : 
     145             : // Multiple inheritance can be used because Task is a pure interface.
     146     3783779 : class V8_EXPORT_PRIVATE CancelableTask : public Cancelable,
     147             :                                          NON_EXPORTED_BASE(public Task) {
     148             :  public:
     149             :   explicit CancelableTask(Isolate* isolate);
     150             :   explicit CancelableTask(CancelableTaskManager* manager);
     151             : 
     152             :   // Task overrides.
     153     1884680 :   void Run() final {
     154     1884680 :     if (TryRun()) {
     155     1687068 :       RunInternal();
     156             :     }
     157     1884399 :   }
     158             : 
     159             :   virtual void RunInternal() = 0;
     160             : 
     161             :  private:
     162             :   DISALLOW_COPY_AND_ASSIGN(CancelableTask);
     163             : };
     164             : 
     165             : // Multiple inheritance can be used because IdleTask is a pure interface.
     166        7506 : class CancelableIdleTask : public Cancelable, public IdleTask {
     167             :  public:
     168             :   explicit CancelableIdleTask(Isolate* isolate);
     169             :   explicit CancelableIdleTask(CancelableTaskManager* manager);
     170             : 
     171             :   // IdleTask overrides.
     172        3753 :   void Run(double deadline_in_seconds) final {
     173        3753 :     if (TryRun()) {
     174        3753 :       RunInternal(deadline_in_seconds);
     175             :     }
     176        3753 :   }
     177             : 
     178             :   virtual void RunInternal(double deadline_in_seconds) = 0;
     179             : 
     180             :  private:
     181             :   DISALLOW_COPY_AND_ASSIGN(CancelableIdleTask);
     182             : };
     183             : 
     184             : }  // namespace internal
     185             : }  // namespace v8
     186             : 
     187             : #endif  // V8_CANCELABLE_TASK_H_

Generated by: LCOV version 1.10