Chromium Code Reviews| 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 |