1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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_
|