OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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/tuple.h" |
| 10 #include "base/raw_scoped_refptr_mismatch_checker.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 |