// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // ScopedCallbackFactory helps in cases where you wish to allocate a Callback // (see base/callback.h), but need to prevent any pending callbacks from // executing when your object gets destroyed. // // EXAMPLE: // // void GatherDataAsynchronously(Callback1::Type* callback); // // class MyClass { // public: // MyClass() : factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { // } // // void Process() { // GatherDataAsynchronously(factory_.NewCallback(&MyClass::GotData)); // } // // private: // void GotData(const Data& data) { // ... // } // // base::ScopedCallbackFactory factory_; // }; // // In the above example, the Process function calls GatherDataAsynchronously to // kick off some asynchronous processing that upon completion will notify a // callback. If in the meantime, the MyClass instance is destroyed, when the // callback runs, it will notice that the MyClass instance is dead, and it will // avoid calling the GotData method. #ifndef BASE_SCOPED_CALLBACK_FACTORY_H_ #define BASE_SCOPED_CALLBACK_FACTORY_H_ #include "base/callback.h" #include "base/weak_ptr.h" namespace base { template class ScopedCallbackFactory { public: explicit ScopedCallbackFactory(T* obj) : weak_factory_(obj) { } typename Callback0::Type* NewCallback( void (T::*method)()) { return new CallbackImpl( weak_factory_.GetWeakPtr(), method); } template typename Callback1::Type* NewCallback( void (T::*method)(Arg1)) { return new CallbackImpl >( weak_factory_.GetWeakPtr(), method); } template typename Callback2::Type* NewCallback( void (T::*method)(Arg1, Arg2)) { return new CallbackImpl >( weak_factory_.GetWeakPtr(), method); } template typename Callback3::Type* NewCallback( void (T::*method)(Arg1, Arg2, Arg3)) { return new CallbackImpl >( weak_factory_.GetWeakPtr(), method); } template typename Callback4::Type* NewCallback( void (T::*method)(Arg1, Arg2, Arg3, Arg4)) { return new CallbackImpl >( weak_factory_.GetWeakPtr(), method); } template typename Callback5::Type* NewCallback( void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) { return new CallbackImpl >( weak_factory_.GetWeakPtr(), method); } void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); } bool HasPendingCallbacks() const { return weak_factory_.HasWeakPtrs(); } private: template class CallbackStorage { public: CallbackStorage(const WeakPtr& obj, Method meth) : obj_(obj), meth_(meth) { } protected: WeakPtr obj_; Method meth_; }; template class CallbackImpl : public CallbackStorage, public CallbackRunner { public: CallbackImpl(const WeakPtr& obj, Method meth) : CallbackStorage(obj, meth) { } virtual void RunWithParams(const Params& params) { // Use "this->" to force C++ to look inside our templatized base class; // see Effective C++, 3rd Ed, item 43, p210 for details. if (!this->obj_) return; DispatchToMethod(this->obj_.get(), this->meth_, params); } }; WeakPtrFactory weak_factory_; }; } // namespace base #endif // BASE_SCOPED_CALLBACK_FACTORY_H_