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