diff options
author | Iain Merrick <husky@google.com> | 2010-10-19 14:37:37 +0100 |
---|---|---|
committer | Iain Merrick <husky@google.com> | 2010-10-19 14:37:37 +0100 |
commit | 3345a6884c488ff3a535c2c9acdd33d74b37e311 (patch) | |
tree | 7784b988ef1698cb6967ea1bdf07616237716c6c /base/scoped_callback_factory.h | |
parent | efc8475837ec58186051f23bb03542620424f6ce (diff) | |
download | external_chromium-3345a6884c488ff3a535c2c9acdd33d74b37e311.zip external_chromium-3345a6884c488ff3a535c2c9acdd33d74b37e311.tar.gz external_chromium-3345a6884c488ff3a535c2c9acdd33d74b37e311.tar.bz2 |
Merge Chromium at 7.0.540.0 : Initial merge by git
Not including third_party/icu as it contains huge data files that break Gerrit, and aren't actually used.
Change-Id: I428a386e70f3b58cacd28677b8cfda282e891e15
Diffstat (limited to 'base/scoped_callback_factory.h')
-rw-r--r-- | base/scoped_callback_factory.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/base/scoped_callback_factory.h b/base/scoped_callback_factory.h new file mode 100644 index 0000000..a2fc1f0 --- /dev/null +++ b/base/scoped_callback_factory.h @@ -0,0 +1,133 @@ +// 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<Data>::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<MyClass> 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 T> +class ScopedCallbackFactory { + public: + explicit ScopedCallbackFactory(T* obj) : weak_factory_(obj) { + } + + typename Callback0::Type* NewCallback( + void (T::*method)()) { + return new CallbackImpl<void (T::*)(), Tuple0 >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1> + typename Callback1<Arg1>::Type* NewCallback( + void (T::*method)(Arg1)) { + return new CallbackImpl<void (T::*)(Arg1), Tuple1<Arg1> >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1, typename Arg2> + typename Callback2<Arg1, Arg2>::Type* NewCallback( + void (T::*method)(Arg1, Arg2)) { + return new CallbackImpl<void (T::*)(Arg1, Arg2), Tuple2<Arg1, Arg2> >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1, typename Arg2, typename Arg3> + typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback( + void (T::*method)(Arg1, Arg2, Arg3)) { + return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3), + Tuple3<Arg1, Arg2, Arg3> >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> + typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback( + void (T::*method)(Arg1, Arg2, Arg3, Arg4)) { + return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3, Arg4), + Tuple4<Arg1, Arg2, Arg3, Arg4> >( + weak_factory_.GetWeakPtr(), method); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4, + typename Arg5> + typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback( + void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) { + return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5), + Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >( + weak_factory_.GetWeakPtr(), method); + } + + void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); } + bool HasPendingCallbacks() const { return weak_factory_.HasWeakPtrs(); } + + private: + template <typename Method> + class CallbackStorage { + public: + CallbackStorage(const WeakPtr<T>& obj, Method meth) + : obj_(obj), + meth_(meth) { + } + + protected: + WeakPtr<T> obj_; + Method meth_; + }; + + template <typename Method, typename Params> + class CallbackImpl : public CallbackStorage<Method>, + public CallbackRunner<Params> { + public: + CallbackImpl(const WeakPtr<T>& obj, Method meth) + : CallbackStorage<Method>(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<T> weak_factory_; +}; + +} // namespace base + +#endif // BASE_SCOPED_CALLBACK_FACTORY_H_ |