• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // ScopedCallbackFactory helps in cases where you wish to allocate a Callback
6 // (see base/callback.h), but need to prevent any pending callbacks from
7 // executing when your object gets destroyed.
8 //
9 // EXAMPLE:
10 //
11 //  void GatherDataAsynchronously(Callback1<Data>::Type* callback);
12 //
13 //  class MyClass {
14 //   public:
15 //    MyClass() : factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
16 //    }
17 //
18 //    void Process() {
19 //      GatherDataAsynchronously(factory_.NewCallback(&MyClass::GotData));
20 //    }
21 //
22 //   private:
23 //    void GotData(const Data& data) {
24 //      ...
25 //    }
26 //
27 //    base::ScopedCallbackFactory<MyClass> factory_;
28 //  };
29 //
30 // In the above example, the Process function calls GatherDataAsynchronously to
31 // kick off some asynchronous processing that upon completion will notify a
32 // callback.  If in the meantime, the MyClass instance is destroyed, when the
33 // callback runs, it will notice that the MyClass instance is dead, and it will
34 // avoid calling the GotData method.
35 
36 #ifndef BASE_MEMORY_SCOPED_CALLBACK_FACTORY_H_
37 #define BASE_MEMORY_SCOPED_CALLBACK_FACTORY_H_
38 
39 #include "base/callback.h"
40 #include "base/memory/weak_ptr.h"
41 
42 namespace base {
43 
44 template <class T>
45 class ScopedCallbackFactory {
46  public:
ScopedCallbackFactory(T * obj)47   explicit ScopedCallbackFactory(T* obj) : weak_factory_(obj) {
48   }
49 
NewCallback(void (T::* method)())50   typename Callback0::Type* NewCallback(
51       void (T::*method)()) {
52     return new CallbackImpl<void (T::*)(), Tuple0 >(
53         weak_factory_.GetWeakPtr(), method);
54   }
55 
56   template <typename Arg1>
NewCallback(void (T::* method)(Arg1))57   typename Callback1<Arg1>::Type* NewCallback(
58       void (T::*method)(Arg1)) {
59     return new CallbackImpl<void (T::*)(Arg1), Tuple1<Arg1> >(
60         weak_factory_.GetWeakPtr(), method);
61   }
62 
63   template <typename Arg1, typename Arg2>
NewCallback(void (T::* method)(Arg1,Arg2))64   typename Callback2<Arg1, Arg2>::Type* NewCallback(
65       void (T::*method)(Arg1, Arg2)) {
66     return new CallbackImpl<void (T::*)(Arg1, Arg2), Tuple2<Arg1, Arg2> >(
67         weak_factory_.GetWeakPtr(), method);
68   }
69 
70   template <typename Arg1, typename Arg2, typename Arg3>
NewCallback(void (T::* method)(Arg1,Arg2,Arg3))71   typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
72       void (T::*method)(Arg1, Arg2, Arg3)) {
73     return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3),
74                             Tuple3<Arg1, Arg2, Arg3> >(
75         weak_factory_.GetWeakPtr(), method);
76   }
77 
78   template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
NewCallback(void (T::* method)(Arg1,Arg2,Arg3,Arg4))79   typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
80       void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
81     return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3, Arg4),
82                             Tuple4<Arg1, Arg2, Arg3, Arg4> >(
83         weak_factory_.GetWeakPtr(), method);
84   }
85 
86   template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
87             typename Arg5>
NewCallback(void (T::* method)(Arg1,Arg2,Arg3,Arg4,Arg5))88   typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
89       void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
90     return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
91                             Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(
92         weak_factory_.GetWeakPtr(), method);
93   }
94 
RevokeAll()95   void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); }
HasPendingCallbacks()96   bool HasPendingCallbacks() const { return weak_factory_.HasWeakPtrs(); }
97 
98  private:
99   template <typename Method>
100   class CallbackStorage {
101    public:
CallbackStorage(const WeakPtr<T> & obj,Method meth)102     CallbackStorage(const WeakPtr<T>& obj, Method meth)
103         : obj_(obj),
104           meth_(meth) {
105     }
106 
107    protected:
108     WeakPtr<T> obj_;
109     Method meth_;
110   };
111 
112   template <typename Method, typename Params>
113   class CallbackImpl : public CallbackStorage<Method>,
114                        public CallbackRunner<Params> {
115    public:
CallbackImpl(const WeakPtr<T> & obj,Method meth)116     CallbackImpl(const WeakPtr<T>& obj, Method meth)
117         : CallbackStorage<Method>(obj, meth) {
118     }
RunWithParams(const Params & params)119     virtual void RunWithParams(const Params& params) {
120       // Use "this->" to force C++ to look inside our templatized base class;
121       // see Effective C++, 3rd Ed, item 43, p210 for details.
122       if (!this->obj_)
123         return;
124       DispatchToMethod(this->obj_.get(), this->meth_, params);
125     }
126   };
127 
128   WeakPtrFactory<T> weak_factory_;
129 };
130 
131 }  // namespace base
132 
133 #endif  // BASE_MEMORY_SCOPED_CALLBACK_FACTORY_H_
134