Chromium Code Reviews| Index: base/prebind.h |
| diff --git a/base/prebind.h b/base/prebind.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..560114543f3ebc2d1ba9a3ac83aba5a09337e62c |
| --- /dev/null |
| +++ b/base/prebind.h |
| @@ -0,0 +1,283 @@ |
| +// Copyright (c) 2011 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. |
| + |
| +#ifndef BASE_PREBIND_H_ |
| +#define BASE_PREBIND_H_ |
| + |
| +#include "base/callback.h" |
| +#include "base/tuple.h" |
| + |
| +namespace base { |
| + |
| +// These classes are argument wrappers that affect the refcounting, and storage |
| +// semantics for prebound arguments. |
| + |
| +template <typename T> |
| +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
|
| + public: |
| + explicit UnretainedWrapper(T* o) : obj_(o) {} |
| + T* get() { return obj_; } |
| + private: |
| + T* obj_; |
| +}; |
| + |
| +template <typename T> |
| +UnretainedWrapper<T> Unretained(T* o) { return UnretainedWrapper<T>(o); } |
| + |
| +template <typename T> |
| +class ConstRefWrapper { |
| + public: |
| + explicit ConstRefWrapper(const T& o) : ptr_(&o) {} |
| + const T* get() { return ptr_; } |
| + private: |
| + const T* ptr_; |
| +}; |
| + |
| +template <typename T> |
| +ConstRefWrapper<T> ConstRef(const T& o) { return ConstRefWrapper<T>(o); } |
| + |
| +// Unwrap for the wrappers above. |
| +template <typename T> |
| +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
|
| + |
| +template <typename T> |
| +T* unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } |
| + |
| +template <typename T> |
| +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
|
| + |
| +// Optional Refcounting. |
| + |
| +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.
|
| +struct MaybeRefcount; |
| + |
| +template <typename O> |
| +struct MaybeRefcount<false, O> { |
| + static void AddRef(const O&) {} |
| + static void Release(const O&) {} |
| +}; |
| + |
| +template <typename O> |
| +struct MaybeRefcount<true, UnretainedWrapper<O> > { |
| + static void AddRef(const UnretainedWrapper<O>&) {} |
| + static void Release(const UnretainedWrapper<O>&) {} |
| +}; |
| + |
| +template <typename O> |
| +struct MaybeRefcount<true, ConstRefWrapper<O> > { |
| + static void AddRef(ConstRefWrapper<O> o) { o.get()->AddRef(); } |
| + static void Release(ConstRefWrapper<O> o) { o.get()->Release(); } |
| +}; |
| + |
| +template <typename O> |
| +struct MaybeRefcount<true, O* > { |
| + static void AddRef(O* o) { o->AddRef(); } |
| + static void Release(O* o) { o->Release(); } |
| +}; |
| + |
| +// The method by which a function is invoked is determined by 3 different |
| +// dimensions: |
| +// |
| +// 1) The type of function (normal, method, const-method) |
| +// 2) The arity of the function |
| +// 3) The number of bound parameters. |
| +// |
| +// The PolymorphicInvokerN classes unwrap the function signature type to |
| +// specialize based on the first two dimensions. The N in PolymorphicInvokerN |
| +// specifies the 3rd dimension. |
| + |
| +template <typename StorageType, typename Sig> |
| +struct FunctionTraits1; |
| + |
| +// 1 -> 0. |
| +template <typename StorageType, typename R, typename X1> |
| +struct FunctionTraits1<StorageType, R(*)(X1)> { |
| + static const bool kShouldRef = false; |
| + static R DoInvoke(InvokerStorageBase* base) { |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + invoker->f_(unwrap(invoker->p1_)); |
| + } |
| +}; |
| + |
| +template <typename StorageType, typename R, typename O> |
| +struct FunctionTraits1<StorageType, R(O::*)()> { |
| + static const bool kShouldRef = true; |
| + static R DoInvoke(InvokerStorageBase* base) { |
| + // TODO(ajwong): Compile time assert the object type matches for all object |
| + // dispatch. |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + (unwrap(invoker->p1_)->*invoker->f_)(); |
| + } |
| +}; |
| + |
| +template <typename StorageType, typename R, typename O> |
| +struct FunctionTraits1<StorageType, R(O::*)() const> { |
| + static const bool kShouldRef = true; |
| + static R DoInvoke(InvokerStorageBase* base) { |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + (unwrap(invoker->p1_)->*invoker->f_)(); |
| + } |
| +}; |
| + |
| +// 2 -> 1. |
| +template <typename StorageType, typename R, typename X1, typename X2> |
| +struct FunctionTraits1<StorageType, R(*)(X1, X2)> { |
| + static const bool kShouldRef = false; |
| + static R DoInvoke(InvokerStorageBase* base, X2 x2) { |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + invoker->f_(unwrap(invoker->p1_), x2); |
| + } |
| +}; |
| + |
| +template <typename StorageType, typename R, typename X1, typename O> |
| +struct FunctionTraits1<StorageType, R(O::*)(X1)> { |
| + static const bool kShouldRef = true; |
| + static R DoInvoke(InvokerStorageBase* base, X1 x1) { |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + (unwrap(invoker->p1_)->*invoker->f_)(x1); |
| + } |
| +}; |
| + |
| +template <typename StorageType, typename R, typename X1, typename O> |
| +struct FunctionTraits1<StorageType, R(O::*)(X1) const> { |
| + static const bool kShouldRef = true; |
| + static R DoInvoke(InvokerStorageBase* base, X1 x1) { |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + (unwrap(invoker->p1_)->*invoker->f_)(x1); |
| + } |
| +}; |
| + |
| +// 2 -> 0 |
| +template <typename StorageType, typename Sig> |
| +struct FunctionTraits2; |
| + |
| +template <typename StorageType, typename R, typename X1, typename X2> |
| +struct FunctionTraits2<StorageType, R(*)(X1,X2)> { |
| + static const bool kShouldRef = false; |
| + static R DoInvoke(InvokerStorageBase* base) { |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + invoker->f_(unwrap(invoker->p1_), unwrap(invoker->p2_)); |
| + } |
| +}; |
| + |
| +template <typename StorageType, typename R, typename O, typename X1> |
| +struct FunctionTraits2<StorageType, R(O::*)(X1)> { |
| + static const bool kShouldRef = true; |
| + static R DoInvoke(InvokerStorageBase* base) { |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + (unwrap(invoker->p1_)->*invoker->f_)(unwrap(invoker->p2_)); |
| + } |
| +}; |
| + |
| +template <typename StorageType, typename R, typename O, typename X1> |
| +struct FunctionTraits2<StorageType, R(O::*)(X1) const> { |
| + static const bool kShouldRef = true; |
| + static R DoInvoke(InvokerStorageBase* base) { |
| + StorageType* invoker = static_cast<StorageType*>(base); |
| + (unwrap(invoker->p1_)->*invoker->f_)(unwrap(invoker->p2_)); |
| + } |
| +}; |
| + |
| +// 3 -> 0 |
| +template <typename StorageType, typename Sig> |
| +struct FunctionTraits3; |
| + |
| + |
| +// These are the actual storage classes for the invokers. |
| + |
| +template <typename T> |
| +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.
|
| + return InvokerStorageHolder<T>(o); |
| +} |
| + |
| +template <typename Sig, typename P1> |
| +class InvokerStorage1 : public InvokerStorageBase { |
| + public: |
| + typedef InvokerStorage1 StorageType; |
| + typedef FunctionTraits1<StorageType, Sig> FunctionTraits; |
| + |
| + InvokerStorage1(Sig f, const P1& p1) : |
| + f_(f), |
| + p1_(p1) { |
| + MaybeRefcount<FunctionTraits::kShouldRef, P1>::AddRef(p1_); |
| + } |
| + |
| + virtual ~InvokerStorage1() { |
| + MaybeRefcount<FunctionTraits::kShouldRef, P1>::Release(p1_); |
| + } |
| + |
| + Sig f_; |
| + P1 p1_; |
| +}; |
| + |
| +template <typename Sig, typename P1, typename P2> |
| +class InvokerStorage2 : public InvokerStorageBase { |
| + public: |
| + typedef InvokerStorage2 StorageType; |
| + typedef FunctionTraits2<StorageType, Sig> FunctionTraits; |
| + |
| + InvokerStorage2(Sig f, const P1& p1, const P2& p2) : |
| + f_(f), |
| + p1_(p1), |
| + p2_(p2) { |
| + MaybeRefcount<FunctionTraits::kShouldRef, P1>::AddRef(p1_); |
| + } |
| + |
| + virtual ~InvokerStorage2() { |
| + MaybeRefcount<FunctionTraits::kShouldRef, P1>::Release(p1_); |
| + } |
| + |
| + Sig f_; |
| + P1 p1_; |
| + P2 p2_; |
| +}; |
| + |
| +template <typename Sig, typename P1, typename P2, typename P3> |
| +class InvokerStorage3 : public InvokerStorageBase { |
| + public: |
| + typedef InvokerStorage3 StorageType; |
| + typedef FunctionTraits3<StorageType, Sig> FunctionTraits; |
| + |
| + InvokerStorage3(Sig f, const P1& p1, const P2& p2, const P3& p3) : |
| + f_(f), |
| + p1_(p1), |
| + p2_(p2), |
| + p3_(p3) { |
| + MaybeRefcount<FunctionTraits::kShouldRef, P1>::AddRef(p1_); |
| + } |
| + |
| + virtual ~InvokerStorage3() { |
| + MaybeRefcount<FunctionTraits::kShouldRef, P1>::Release(p1_); |
| + } |
| + |
| + Sig f_; |
| + P1 p1_; |
| + P2 p2_; |
| + P3 p3_; |
| +}; |
| + |
| +template <typename Sig, typename P1> |
| +InvokerStorageHolder<InvokerStorage1<Sig, P1> > |
| +Prebind(Sig f, const P1& p1) { |
| + return MakeInvokerStorageHolder(new InvokerStorage1<Sig, P1>(f, p1)); |
| +} |
| + |
| +// Function 2 -> 0 |
| +template <typename Sig, typename P1, typename P2> |
| +InvokerStorageHolder<InvokerStorage2<Sig, P1, P2> > |
| +Prebind(Sig f, const P1& p1, const P2& p2) { |
| + return MakeInvokerStorageHolder(new InvokerStorage2<Sig, P1, P2>(f, p1, p2)); |
| +} |
| + |
| +// Function 3 -> 0 |
| +template <typename Sig, typename P1, typename P2, typename P3> |
| +InvokerStorageHolder<InvokerStorage3<Sig, P1, P2, P3> > |
| +Prebind(Sig f, const P1& p1, const P2& p2, const P3& p3) { |
| + return MakeInvokerStorageHolder( |
| + new InvokerStorage3<Sig, P1, P2, P3>(p1, p2, p3)); |
| +} |
| + |
| +} // namespace base |
| + |
| +#endif // BASE_PREBIND_H_ |