Home | History | Annotate | Download | only in memory
      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:
     47   explicit ScopedCallbackFactory(T* obj) : weak_factory_(obj) {
     48   }
     49 
     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>
     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>
     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>
     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>
     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>
     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 
     95   void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); }
     96   bool HasPendingCallbacks() const { return weak_factory_.HasWeakPtrs(); }
     97 
     98  private:
     99   template <typename Method>
    100   class CallbackStorage {
    101    public:
    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:
    116     CallbackImpl(const WeakPtr<T>& obj, Method meth)
    117         : CallbackStorage<Method>(obj, meth) {
    118     }
    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