OLD | NEW |
| (Empty) |
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_ | |
OLD | NEW |