Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 The Chromium 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 BASE_CALLBACK_OLD_H_
      6 #define BASE_CALLBACK_OLD_H_
      7 #pragma once
      8 
      9 #include "base/memory/raw_scoped_refptr_mismatch_checker.h"
     10 #include "base/tuple.h"
     11 
     12 // Callback --------------------------------------------------------------------
     13 //
     14 // A Callback is like a Task but with unbound parameters. It is basically an
     15 // object-oriented function pointer.
     16 //
     17 // Callbacks are designed to work with Tuples.  A set of helper functions and
     18 // classes is provided to hide the Tuple details from the consumer.  Client
     19 // code will generally work with the CallbackRunner base class, which merely
     20 // provides a Run method and is returned by the New* functions. This allows
     21 // users to not care which type of class implements the callback, only that it
     22 // has a certain number and type of arguments.
     23 //
     24 // The implementation of this is done by CallbackImpl, which inherits
     25 // CallbackStorage to store the data. This allows the storage of the data
     26 // (requiring the class type T) to be hidden from users, who will want to call
     27 // this regardless of the implementor's type T.
     28 //
     29 // Note that callbacks currently have no facility for cancelling or abandoning
     30 // them. We currently handle this at a higher level for cases where this is
     31 // necessary. The pointer in a callback must remain valid until the callback
     32 // is made.
     33 //
     34 // Like Task, the callback executor is responsible for deleting the callback
     35 // pointer once the callback has executed.
     36 //
     37 // Example client usage:
     38 //   void Object::DoStuff(int, string);
     39 //   Callback2<int, string>::Type* callback =
     40 //       NewCallback(obj, &Object::DoStuff);
     41 //   callback->Run(5, string("hello"));
     42 //   delete callback;
     43 // or, equivalently, using tuples directly:
     44 //   CallbackRunner<Tuple2<int, string> >* callback =
     45 //       NewCallback(obj, &Object::DoStuff);
     46 //   callback->RunWithParams(MakeTuple(5, string("hello")));
     47 //
     48 // There is also a 0-args version that returns a value.  Example:
     49 //   int Object::GetNextInt();
     50 //   CallbackWithReturnValue<int>::Type* callback =
     51 //       NewCallbackWithReturnValue(obj, &Object::GetNextInt);
     52 //   int next_int = callback->Run();
     53 //   delete callback;
     54 
     55 // Base for all Callbacks that handles storage of the pointers.
     56 template <class T, typename Method>
     57 class CallbackStorage {
     58  public:
     59   CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {
     60   }
     61 
     62  protected:
     63   T* obj_;
     64   Method meth_;
     65 };
     66 
     67 // Interface that is exposed to the consumer, that does the actual calling
     68 // of the method.
     69 template <typename Params>
     70 class CallbackRunner {
     71  public:
     72   typedef Params TupleType;
     73 
     74   virtual ~CallbackRunner() {}
     75   virtual void RunWithParams(const Params& params) = 0;
     76 
     77   // Convenience functions so callers don't have to deal with Tuples.
     78   inline void Run() {
     79     RunWithParams(Tuple0());
     80   }
     81 
     82   template <typename Arg1>
     83   inline void Run(const Arg1& a) {
     84     RunWithParams(Params(a));
     85   }
     86 
     87   template <typename Arg1, typename Arg2>
     88   inline void Run(const Arg1& a, const Arg2& b) {
     89     RunWithParams(Params(a, b));
     90   }
     91 
     92   template <typename Arg1, typename Arg2, typename Arg3>
     93   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {
     94     RunWithParams(Params(a, b, c));
     95   }
     96 
     97   template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
     98   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {
     99     RunWithParams(Params(a, b, c, d));
    100   }
    101 
    102   template <typename Arg1, typename Arg2, typename Arg3,
    103             typename Arg4, typename Arg5>
    104   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,
    105                   const Arg4& d, const Arg5& e) {
    106     RunWithParams(Params(a, b, c, d, e));
    107   }
    108 };
    109 
    110 template <class T, typename Method, typename Params>
    111 class CallbackImpl : public CallbackStorage<T, Method>,
    112                      public CallbackRunner<Params> {
    113  public:
    114   CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
    115   }
    116   virtual void RunWithParams(const Params& params) {
    117     // use "this->" to force C++ to look inside our templatized base class; see
    118     // Effective C++, 3rd Ed, item 43, p210 for details.
    119     DispatchToMethod(this->obj_, this->meth_, params);
    120   }
    121 };
    122 
    123 // 0-arg implementation
    124 struct Callback0 {
    125   typedef CallbackRunner<Tuple0> Type;
    126 };
    127 
    128 template <class T>
    129 typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
    130   return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
    131 }
    132 
    133 // 1-arg implementation
    134 template <typename Arg1>
    135 struct Callback1 {
    136   typedef CallbackRunner<Tuple1<Arg1> > Type;
    137 };
    138 
    139 template <class T, typename Arg1>
    140 typename Callback1<Arg1>::Type* NewCallback(T* object,
    141                                             void (T::*method)(Arg1)) {
    142   return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);
    143 }
    144 
    145 // 2-arg implementation
    146 template <typename Arg1, typename Arg2>
    147 struct Callback2 {
    148   typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
    149 };
    150 
    151 template <class T, typename Arg1, typename Arg2>
    152 typename Callback2<Arg1, Arg2>::Type* NewCallback(
    153     T* object,
    154     void (T::*method)(Arg1, Arg2)) {
    155   return new CallbackImpl<T, void (T::*)(Arg1, Arg2),
    156       Tuple2<Arg1, Arg2> >(object, method);
    157 }
    158 
    159 // 3-arg implementation
    160 template <typename Arg1, typename Arg2, typename Arg3>
    161 struct Callback3 {
    162   typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
    163 };
    164 
    165 template <class T, typename Arg1, typename Arg2, typename Arg3>
    166 typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
    167     T* object,
    168     void (T::*method)(Arg1, Arg2, Arg3)) {
    169   return new CallbackImpl<T,  void (T::*)(Arg1, Arg2, Arg3),
    170       Tuple3<Arg1, Arg2, Arg3> >(object, method);
    171 }
    172 
    173 // 4-arg implementation
    174 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
    175 struct Callback4 {
    176   typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
    177 };
    178 
    179 template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
    180 typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
    181     T* object,
    182     void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
    183   return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),
    184       Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);
    185 }
    186 
    187 // 5-arg implementation
    188 template <typename Arg1, typename Arg2, typename Arg3,
    189           typename Arg4, typename Arg5>
    190 struct Callback5 {
    191   typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
    192 };
    193 
    194 template <class T, typename Arg1, typename Arg2,
    195           typename Arg3, typename Arg4, typename Arg5>
    196 typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
    197     T* object,
    198     void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
    199   return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
    200       Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);
    201 }
    202 
    203 // An UnboundMethod is a wrapper for a method where the actual object is
    204 // provided at Run dispatch time.
    205 template <class T, class Method, class Params>
    206 class UnboundMethod {
    207  public:
    208   UnboundMethod(Method m, const Params& p) : m_(m), p_(p) {
    209     COMPILE_ASSERT(
    210         (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
    211         badunboundmethodparams);
    212   }
    213   void Run(T* obj) const {
    214     DispatchToMethod(obj, m_, p_);
    215   }
    216  private:
    217   Method m_;
    218   Params p_;
    219 };
    220 
    221 // Return value implementation with no args.
    222 template <typename ReturnValue>
    223 struct CallbackWithReturnValue {
    224   class Type {
    225    public:
    226     virtual ~Type() {}
    227     virtual ReturnValue Run() = 0;
    228   };
    229 };
    230 
    231 template <class T, typename Method, typename ReturnValue>
    232 class CallbackWithReturnValueImpl
    233     : public CallbackStorage<T, Method>,
    234       public CallbackWithReturnValue<ReturnValue>::Type {
    235  public:
    236   CallbackWithReturnValueImpl(T* obj, Method meth)
    237       : CallbackStorage<T, Method>(obj, meth) {}
    238 
    239   virtual ReturnValue Run() {
    240     return (this->obj_->*(this->meth_))();
    241   }
    242 
    243  protected:
    244   virtual ~CallbackWithReturnValueImpl() {}
    245 };
    246 
    247 template <class T, typename ReturnValue>
    248 typename CallbackWithReturnValue<ReturnValue>::Type*
    249 NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) {
    250   return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>(
    251       object, method);
    252 }
    253 
    254 #endif  // BASE_CALLBACK_OLD_H_
    255