summaryrefslogtreecommitdiffstats
path: root/base/scoped_callback_factory.h
diff options
context:
space:
mode:
authorIain Merrick <husky@google.com>2010-10-19 14:37:37 +0100
committerIain Merrick <husky@google.com>2010-10-19 14:37:37 +0100
commit3345a6884c488ff3a535c2c9acdd33d74b37e311 (patch)
tree7784b988ef1698cb6967ea1bdf07616237716c6c /base/scoped_callback_factory.h
parentefc8475837ec58186051f23bb03542620424f6ce (diff)
downloadexternal_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.h133
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_