OLD | NEW |
---|---|
(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_ | |
OLD | NEW |