tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

task.h (7948B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 
      7 #ifndef BASE_TASK_H_
      8 #define BASE_TASK_H_
      9 
     10 #include "base/revocable_store.h"
     11 #include "base/tuple.h"
     12 
     13 #include "nsISupportsImpl.h"
     14 #include "nsThreadUtils.h"
     15 
     16 #include <type_traits>
     17 #include <utility>
     18 
     19 // Helper functions so that we can call a function a pass it arguments that come
     20 // from a Tuple.
     21 
     22 namespace details {
     23 
     24 // Call the given method on the given object. Arguments are passed by move
     25 // semantics from the given tuple. If the tuple has length N, the sequence must
     26 // be IndexSequence<0, 1, ..., N-1>.
     27 template <size_t... Indices, class ObjT, class Method, typename... Args>
     28 void CallMethod(std::index_sequence<Indices...>, ObjT* obj, Method method,
     29                std::tuple<Args...>& arg) {
     30  (obj->*method)(std::move(std::get<Indices>(arg))...);
     31 }
     32 
     33 // Same as above, but call a function.
     34 template <size_t... Indices, typename Function, typename... Args>
     35 void CallFunction(std::index_sequence<Indices...>, Function function,
     36                  std::tuple<Args...>& arg) {
     37  (*function)(std::move(std::get<Indices>(arg))...);
     38 }
     39 
     40 }  // namespace details
     41 
     42 // Call a method on the given object. Arguments are passed by move semantics
     43 // from the given tuple.
     44 template <class ObjT, class Method, typename... Args>
     45 void DispatchTupleToMethod(ObjT* obj, Method method, std::tuple<Args...>& arg) {
     46  details::CallMethod(std::index_sequence_for<Args...>{}, obj, method, arg);
     47 }
     48 
     49 // Same as above, but call a function.
     50 template <typename Function, typename... Args>
     51 void DispatchTupleToFunction(Function function, std::tuple<Args...>& arg) {
     52  details::CallFunction(std::index_sequence_for<Args...>{}, function, arg);
     53 }
     54 
     55 // General task implementations ------------------------------------------------
     56 
     57 // Task to delete an object
     58 template <class T>
     59 class DeleteTask : public mozilla::CancelableRunnable {
     60 public:
     61  explicit DeleteTask(T* obj)
     62      : mozilla::CancelableRunnable("DeleteTask"), obj_(obj) {}
     63  NS_IMETHOD Run() override {
     64    delete obj_;
     65    return NS_OK;
     66  }
     67  virtual nsresult Cancel() override {
     68    obj_ = NULL;
     69    return NS_OK;
     70  }
     71 
     72 private:
     73  T* MOZ_UNSAFE_REF(
     74      "The validity of this pointer must be enforced by "
     75      "external factors.") obj_;
     76 };
     77 
     78 // RunnableMethodTraits --------------------------------------------------------
     79 //
     80 // This traits-class is used by RunnableMethod to manage the lifetime of the
     81 // callee object.  By default, it is assumed that the callee supports AddRef
     82 // and Release methods.  A particular class can specialize this template to
     83 // define other lifetime management.  For example, if the callee is known to
     84 // live longer than the RunnableMethod object, then a RunnableMethodTraits
     85 // struct could be defined with empty RetainCallee and ReleaseCallee methods.
     86 
     87 template <class T>
     88 struct RunnableMethodTraits {
     89  static void RetainCallee(T* obj) { obj->AddRef(); }
     90  static void ReleaseCallee(T* obj) { obj->Release(); }
     91 };
     92 
     93 // This allows using the NewRunnableMethod() functions with a const pointer
     94 // to the callee object. See the similar support in nsRefPtr for a rationale
     95 // of why this is reasonable.
     96 template <class T>
     97 struct RunnableMethodTraits<const T> {
     98  static void RetainCallee(const T* obj) { const_cast<T*>(obj)->AddRef(); }
     99  static void ReleaseCallee(const T* obj) { const_cast<T*>(obj)->Release(); }
    100 };
    101 
    102 // RunnableMethod and RunnableFunction -----------------------------------------
    103 //
    104 // Runnable methods are a type of task that call a function on an object when
    105 // they are run. We implement both an object and a set of NewRunnableMethod and
    106 // NewRunnableFunction functions for convenience. These functions are
    107 // overloaded and will infer the template types, simplifying calling code.
    108 //
    109 // The template definitions all use the following names:
    110 // T                - the class type of the object you're supplying
    111 //                    this is not needed for the Static version of the call
    112 // Method/Function  - the signature of a pointer to the method or function you
    113 //                    want to call
    114 // Param            - the parameter(s) to the method, possibly packed as a Tuple
    115 // A                - the first parameter (if any) to the method
    116 // B                - the second parameter (if any) to the mathod
    117 //
    118 // Put these all together and you get an object that can call a method whose
    119 // signature is:
    120 //   R T::MyFunction([A[, B]])
    121 //
    122 // Usage:
    123 // PostTask(NewRunnableMethod(object, &Object::method[, a[, b]])
    124 // PostTask(NewRunnableFunction(&function[, a[, b]])
    125 
    126 // RunnableMethod and NewRunnableMethod implementation -------------------------
    127 
    128 template <class T, class Method, class Params>
    129 class RunnableMethod : public mozilla::CancelableRunnable,
    130                       public RunnableMethodTraits<T> {
    131 public:
    132  RunnableMethod(T* obj, Method meth, Params&& params)
    133      : mozilla::CancelableRunnable("RunnableMethod"),
    134        obj_(obj),
    135        meth_(meth),
    136        params_(std::forward<Params>(params)) {
    137    this->RetainCallee(obj_);
    138  }
    139  ~RunnableMethod() { ReleaseCallee(); }
    140 
    141  NS_IMETHOD Run() override {
    142    if (obj_) DispatchTupleToMethod(obj_, meth_, params_);
    143    return NS_OK;
    144  }
    145 
    146  virtual nsresult Cancel() override {
    147    ReleaseCallee();
    148    return NS_OK;
    149  }
    150 
    151 private:
    152  void ReleaseCallee() {
    153    if (obj_) {
    154      RunnableMethodTraits<T>::ReleaseCallee(obj_);
    155      obj_ = nullptr;
    156    }
    157  }
    158 
    159  // This is owning because of the RetainCallee and ReleaseCallee calls in the
    160  // constructor and destructor.
    161  T* MOZ_OWNING_REF obj_;
    162  Method meth_;
    163  Params params_;
    164 };
    165 
    166 namespace dont_add_new_uses_of_this {
    167 
    168 // Don't add new uses of this!!!!
    169 template <class T, class Method, typename... Args>
    170 inline already_AddRefed<mozilla::Runnable> NewRunnableMethod(T* object,
    171                                                             Method method,
    172                                                             Args&&... args) {
    173  typedef std::tuple<std::decay_t<Args>...> ArgsTuple;
    174  RefPtr<mozilla::Runnable> t = new RunnableMethod<T, Method, ArgsTuple>(
    175      object, method, std::make_tuple(std::forward<Args>(args)...));
    176  return t.forget();
    177 }
    178 
    179 }  // namespace dont_add_new_uses_of_this
    180 
    181 // RunnableFunction and NewRunnableFunction implementation ---------------------
    182 
    183 template <class Function, class Params>
    184 class RunnableFunction : public mozilla::CancelableRunnable {
    185 public:
    186  RunnableFunction(const char* name, Function function, Params&& params)
    187      : mozilla::CancelableRunnable(name),
    188        function_(function),
    189        params_(std::forward<Params>(params)) {}
    190 
    191  ~RunnableFunction() {}
    192 
    193  NS_IMETHOD Run() override {
    194    if (function_) DispatchTupleToFunction(function_, params_);
    195    return NS_OK;
    196  }
    197 
    198  virtual nsresult Cancel() override {
    199    function_ = nullptr;
    200    return NS_OK;
    201  }
    202 
    203  Function function_;
    204  Params params_;
    205 };
    206 
    207 template <class Function, typename... Args>
    208 inline already_AddRefed<mozilla::CancelableRunnable>
    209 NewCancelableRunnableFunction(const char* name, Function function,
    210                              Args&&... args) {
    211  typedef std::tuple<std::decay_t<Args>...> ArgsTuple;
    212  RefPtr<mozilla::CancelableRunnable> t =
    213      new RunnableFunction<Function, ArgsTuple>(
    214          name, function, std::make_tuple(std::forward<Args>(args)...));
    215  return t.forget();
    216 }
    217 
    218 template <class Function, typename... Args>
    219 inline already_AddRefed<mozilla::Runnable> NewRunnableFunction(
    220    const char* name, Function function, Args&&... args) {
    221  typedef std::tuple<std::decay_t<Args>...> ArgsTuple;
    222  RefPtr<mozilla::Runnable> t = new RunnableFunction<Function, ArgsTuple>(
    223      name, function, std::make_tuple(std::forward<Args>(args)...));
    224  return t.forget();
    225 }
    226 
    227 #endif  // BASE_TASK_H_