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. 56template <class T, typename Method> 57class 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. 69template <typename Params> 70class 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 110template <class T, typename Method, typename Params> 111class 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 124struct Callback0 { 125 typedef CallbackRunner<Tuple0> Type; 126}; 127 128template <class T> 129typename Callback0::Type* NewCallback(T* object, void (T::*method)()) { 130 return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method); 131} 132 133// 1-arg implementation 134template <typename Arg1> 135struct Callback1 { 136 typedef CallbackRunner<Tuple1<Arg1> > Type; 137}; 138 139template <class T, typename Arg1> 140typename 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 146template <typename Arg1, typename Arg2> 147struct Callback2 { 148 typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type; 149}; 150 151template <class T, typename Arg1, typename Arg2> 152typename 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 160template <typename Arg1, typename Arg2, typename Arg3> 161struct Callback3 { 162 typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type; 163}; 164 165template <class T, typename Arg1, typename Arg2, typename Arg3> 166typename 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 174template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> 175struct Callback4 { 176 typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type; 177}; 178 179template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> 180typename 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 188template <typename Arg1, typename Arg2, typename Arg3, 189 typename Arg4, typename Arg5> 190struct Callback5 { 191 typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type; 192}; 193 194template <class T, typename Arg1, typename Arg2, 195 typename Arg3, typename Arg4, typename Arg5> 196typename 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. 205template <class T, class Method, class Params> 206class 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. 222template <typename ReturnValue> 223struct CallbackWithReturnValue { 224 class Type { 225 public: 226 virtual ~Type() {} 227 virtual ReturnValue Run() = 0; 228 }; 229}; 230 231template <class T, typename Method, typename ReturnValue> 232class 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 247template <class T, typename ReturnValue> 248typename CallbackWithReturnValue<ReturnValue>::Type* 249NewCallbackWithReturnValue(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