Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: base/prebind.h

Issue 6109007: Unified callback system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/base
Patch Set: Ready for another structural review. (not optimized) Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« base/callback_unittest.cc ('K') | « base/callback_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 #ifndef BASE_PREBIND_H_
6 #define BASE_PREBIND_H_
7
8 #include "base/callback.h"
9 #include "base/tuple.h"
10
11 namespace base {
12
13 // These classes are argument wrappers that affect the refcounting, and storage
14 // semantics for prebound arguments.
15
16 template <typename T>
17 class UnretainedWrapper {
darin (slow to review) 2011/02/01 00:35:56 it seems like it would be helpful to put classes l
awong 2011/02/01 01:21:38 Yep...will do that in next iteration. Was avoidin
18 public:
19 explicit UnretainedWrapper(T* o) : obj_(o) {}
20 T* get() { return obj_; }
21 private:
22 T* obj_;
23 };
24
25 template <typename T>
26 UnretainedWrapper<T> Unretained(T* o) { return UnretainedWrapper<T>(o); }
27
28 template <typename T>
29 class ConstRefWrapper {
30 public:
31 explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
32 const T* get() { return ptr_; }
33 private:
34 const T* ptr_;
35 };
36
37 template <typename T>
38 ConstRefWrapper<T> ConstRef(const T& o) { return ConstRefWrapper<T>(o); }
39
40 // Unwrap for the wrappers above.
41 template <typename T>
42 T unwrap(T o) { return o; }
darin (slow to review) 2011/02/01 00:35:56 why is it "unwrap" and not "Unwrap"?
awong 2011/02/01 01:21:38 More typoing. I haven't actually scrubbed this fo
43
44 template <typename T>
45 T* unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); }
46
47 template <typename T>
48 const T* unwrap(ConstRefWrapper<T> const_ref) { return const_ref.get(); }
darin (slow to review) 2011/02/01 00:35:56 why are Unretained, ConstRef, and unwrap defined i
awong 2011/02/01 01:21:38 I feel like they actually belong here. They are p
49
50 // Optional Refcounting.
51
52 template <bool ref, typename O>
darin (slow to review) 2011/02/01 00:35:56 "O" seems like a poor typename because it looks to
awong 2011/02/01 01:21:38 Yeah, that seems better. Will change.
53 struct MaybeRefcount;
54
55 template <typename O>
56 struct MaybeRefcount<false, O> {
57 static void AddRef(const O&) {}
58 static void Release(const O&) {}
59 };
60
61 template <typename O>
62 struct MaybeRefcount<true, UnretainedWrapper<O> > {
63 static void AddRef(const UnretainedWrapper<O>&) {}
64 static void Release(const UnretainedWrapper<O>&) {}
65 };
66
67 template <typename O>
68 struct MaybeRefcount<true, ConstRefWrapper<O> > {
69 static void AddRef(ConstRefWrapper<O> o) { o.get()->AddRef(); }
70 static void Release(ConstRefWrapper<O> o) { o.get()->Release(); }
71 };
72
73 template <typename O>
74 struct MaybeRefcount<true, O* > {
75 static void AddRef(O* o) { o->AddRef(); }
76 static void Release(O* o) { o->Release(); }
77 };
78
79 // The method by which a function is invoked is determined by 3 different
80 // dimensions:
81 //
82 // 1) The type of function (normal, method, const-method)
83 // 2) The arity of the function
84 // 3) The number of bound parameters.
85 //
86 // The PolymorphicInvokerN classes unwrap the function signature type to
87 // specialize based on the first two dimensions. The N in PolymorphicInvokerN
88 // specifies the 3rd dimension.
89
90 template <typename StorageType, typename Sig>
91 struct FunctionTraits1;
92
93 // 1 -> 0.
94 template <typename StorageType, typename R, typename X1>
95 struct FunctionTraits1<StorageType, R(*)(X1)> {
96 static const bool kShouldRef = false;
97 static R DoInvoke(InvokerStorageBase* base) {
98 StorageType* invoker = static_cast<StorageType*>(base);
99 invoker->f_(unwrap(invoker->p1_));
100 }
101 };
102
103 template <typename StorageType, typename R, typename O>
104 struct FunctionTraits1<StorageType, R(O::*)()> {
105 static const bool kShouldRef = true;
106 static R DoInvoke(InvokerStorageBase* base) {
107 // TODO(ajwong): Compile time assert the object type matches for all object
108 // dispatch.
109 StorageType* invoker = static_cast<StorageType*>(base);
110 (unwrap(invoker->p1_)->*invoker->f_)();
111 }
112 };
113
114 template <typename StorageType, typename R, typename O>
115 struct FunctionTraits1<StorageType, R(O::*)() const> {
116 static const bool kShouldRef = true;
117 static R DoInvoke(InvokerStorageBase* base) {
118 StorageType* invoker = static_cast<StorageType*>(base);
119 (unwrap(invoker->p1_)->*invoker->f_)();
120 }
121 };
122
123 // 2 -> 1.
124 template <typename StorageType, typename R, typename X1, typename X2>
125 struct FunctionTraits1<StorageType, R(*)(X1, X2)> {
126 static const bool kShouldRef = false;
127 static R DoInvoke(InvokerStorageBase* base, X2 x2) {
128 StorageType* invoker = static_cast<StorageType*>(base);
129 invoker->f_(unwrap(invoker->p1_), x2);
130 }
131 };
132
133 template <typename StorageType, typename R, typename X1, typename O>
134 struct FunctionTraits1<StorageType, R(O::*)(X1)> {
135 static const bool kShouldRef = true;
136 static R DoInvoke(InvokerStorageBase* base, X1 x1) {
137 StorageType* invoker = static_cast<StorageType*>(base);
138 (unwrap(invoker->p1_)->*invoker->f_)(x1);
139 }
140 };
141
142 template <typename StorageType, typename R, typename X1, typename O>
143 struct FunctionTraits1<StorageType, R(O::*)(X1) const> {
144 static const bool kShouldRef = true;
145 static R DoInvoke(InvokerStorageBase* base, X1 x1) {
146 StorageType* invoker = static_cast<StorageType*>(base);
147 (unwrap(invoker->p1_)->*invoker->f_)(x1);
148 }
149 };
150
151 // 2 -> 0
152 template <typename StorageType, typename Sig>
153 struct FunctionTraits2;
154
155 template <typename StorageType, typename R, typename X1, typename X2>
156 struct FunctionTraits2<StorageType, R(*)(X1,X2)> {
157 static const bool kShouldRef = false;
158 static R DoInvoke(InvokerStorageBase* base) {
159 StorageType* invoker = static_cast<StorageType*>(base);
160 invoker->f_(unwrap(invoker->p1_), unwrap(invoker->p2_));
161 }
162 };
163
164 template <typename StorageType, typename R, typename O, typename X1>
165 struct FunctionTraits2<StorageType, R(O::*)(X1)> {
166 static const bool kShouldRef = true;
167 static R DoInvoke(InvokerStorageBase* base) {
168 StorageType* invoker = static_cast<StorageType*>(base);
169 (unwrap(invoker->p1_)->*invoker->f_)(unwrap(invoker->p2_));
170 }
171 };
172
173 template <typename StorageType, typename R, typename O, typename X1>
174 struct FunctionTraits2<StorageType, R(O::*)(X1) const> {
175 static const bool kShouldRef = true;
176 static R DoInvoke(InvokerStorageBase* base) {
177 StorageType* invoker = static_cast<StorageType*>(base);
178 (unwrap(invoker->p1_)->*invoker->f_)(unwrap(invoker->p2_));
179 }
180 };
181
182 // 3 -> 0
183 template <typename StorageType, typename Sig>
184 struct FunctionTraits3;
185
186
187 // These are the actual storage classes for the invokers.
188
189 template <typename T>
190 InvokerStorageHolder<T> MakeInvokerStorageHolder(T* o) {
darin (slow to review) 2011/02/01 00:35:56 shouldn't this go in callback.h near the InvokerSt
awong 2011/02/01 01:21:38 Yes....will move.
191 return InvokerStorageHolder<T>(o);
192 }
193
194 template <typename Sig, typename P1>
195 class InvokerStorage1 : public InvokerStorageBase {
196 public:
197 typedef InvokerStorage1 StorageType;
198 typedef FunctionTraits1<StorageType, Sig> FunctionTraits;
199
200 InvokerStorage1(Sig f, const P1& p1) :
201 f_(f),
202 p1_(p1) {
203 MaybeRefcount<FunctionTraits::kShouldRef, P1>::AddRef(p1_);
204 }
205
206 virtual ~InvokerStorage1() {
207 MaybeRefcount<FunctionTraits::kShouldRef, P1>::Release(p1_);
208 }
209
210 Sig f_;
211 P1 p1_;
212 };
213
214 template <typename Sig, typename P1, typename P2>
215 class InvokerStorage2 : public InvokerStorageBase {
216 public:
217 typedef InvokerStorage2 StorageType;
218 typedef FunctionTraits2<StorageType, Sig> FunctionTraits;
219
220 InvokerStorage2(Sig f, const P1& p1, const P2& p2) :
221 f_(f),
222 p1_(p1),
223 p2_(p2) {
224 MaybeRefcount<FunctionTraits::kShouldRef, P1>::AddRef(p1_);
225 }
226
227 virtual ~InvokerStorage2() {
228 MaybeRefcount<FunctionTraits::kShouldRef, P1>::Release(p1_);
229 }
230
231 Sig f_;
232 P1 p1_;
233 P2 p2_;
234 };
235
236 template <typename Sig, typename P1, typename P2, typename P3>
237 class InvokerStorage3 : public InvokerStorageBase {
238 public:
239 typedef InvokerStorage3 StorageType;
240 typedef FunctionTraits3<StorageType, Sig> FunctionTraits;
241
242 InvokerStorage3(Sig f, const P1& p1, const P2& p2, const P3& p3) :
243 f_(f),
244 p1_(p1),
245 p2_(p2),
246 p3_(p3) {
247 MaybeRefcount<FunctionTraits::kShouldRef, P1>::AddRef(p1_);
248 }
249
250 virtual ~InvokerStorage3() {
251 MaybeRefcount<FunctionTraits::kShouldRef, P1>::Release(p1_);
252 }
253
254 Sig f_;
255 P1 p1_;
256 P2 p2_;
257 P3 p3_;
258 };
259
260 template <typename Sig, typename P1>
261 InvokerStorageHolder<InvokerStorage1<Sig, P1> >
262 Prebind(Sig f, const P1& p1) {
263 return MakeInvokerStorageHolder(new InvokerStorage1<Sig, P1>(f, p1));
264 }
265
266 // Function 2 -> 0
267 template <typename Sig, typename P1, typename P2>
268 InvokerStorageHolder<InvokerStorage2<Sig, P1, P2> >
269 Prebind(Sig f, const P1& p1, const P2& p2) {
270 return MakeInvokerStorageHolder(new InvokerStorage2<Sig, P1, P2>(f, p1, p2));
271 }
272
273 // Function 3 -> 0
274 template <typename Sig, typename P1, typename P2, typename P3>
275 InvokerStorageHolder<InvokerStorage3<Sig, P1, P2, P3> >
276 Prebind(Sig f, const P1& p1, const P2& p2, const P3& p3) {
277 return MakeInvokerStorageHolder(
278 new InvokerStorage3<Sig, P1, P2, P3>(p1, p2, p3));
279 }
280
281 } // namespace base
282
283 #endif // BASE_PREBIND_H_
OLDNEW
« base/callback_unittest.cc ('K') | « base/callback_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698