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