• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
CallbackStorage(T * obj,Method meth)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 
~CallbackRunner()74   virtual ~CallbackRunner() {}
75   virtual void RunWithParams(const Params& params) = 0;
76 
77   // Convenience functions so callers don't have to deal with Tuples.
Run()78   inline void Run() {
79     RunWithParams(Tuple0());
80   }
81 
82   template <typename Arg1>
Run(const Arg1 & a)83   inline void Run(const Arg1& a) {
84     RunWithParams(Params(a));
85   }
86 
87   template <typename Arg1, typename Arg2>
Run(const Arg1 & a,const Arg2 & b)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>
Run(const Arg1 & a,const Arg2 & b,const Arg3 & c)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>
Run(const Arg1 & a,const Arg2 & b,const Arg3 & c,const Arg4 & d)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>
Run(const Arg1 & a,const Arg2 & b,const Arg3 & c,const Arg4 & d,const Arg5 & e)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:
CallbackImpl(T * obj,Method meth)114   CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
115   }
RunWithParams(const Params & params)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>
NewCallback(T * object,void (T::* method)())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>
NewCallback(T * object,void (T::* method)(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>
NewCallback(T * object,void (T::* method)(Arg1,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>
NewCallback(T * object,void (T::* method)(Arg1,Arg2,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>
NewCallback(T * object,void (T::* method)(Arg1,Arg2,Arg3,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>
NewCallback(T * object,void (T::* method)(Arg1,Arg2,Arg3,Arg4,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:
UnboundMethod(Method m,const Params & p)208   UnboundMethod(Method m, const Params& p) : m_(m), p_(p) {
209     COMPILE_ASSERT(
210         (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
211         badunboundmethodparams);
212   }
Run(T * obj)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:
~TypeCallbackWithReturnValue226     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:
CallbackWithReturnValueImpl(T * obj,Method meth)236   CallbackWithReturnValueImpl(T* obj, Method meth)
237       : CallbackStorage<T, Method>(obj, meth) {}
238 
Run()239   virtual ReturnValue Run() {
240     return (this->obj_->*(this->meth_))();
241   }
242 
243  protected:
~CallbackWithReturnValueImpl()244   virtual ~CallbackWithReturnValueImpl() {}
245 };
246 
247 template <class T, typename ReturnValue>
248 typename CallbackWithReturnValue<ReturnValue>::Type*
NewCallbackWithReturnValue(T * object,ReturnValue (T::* method)())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