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

Generated by: LCOV version 1.10