Bug 1056356 - Add support for nsRefPtr<const T>. r=froydnj

--HG--
extra : rebase_source : 7b86c6e7bc47c7b3ebc19075559cf0f7d24ededf
This commit is contained in:
Botond Ballo 2015-08-05 13:52:06 -04:00
Родитель 82a19a631c
Коммит 1ad5e05028
2 изменённых файлов: 74 добавлений и 6 удалений

Просмотреть файл

@ -29,7 +29,7 @@ private:
assign_with_AddRef(T* aRawPtr)
{
if (aRawPtr) {
aRawPtr->AddRef();
AddRefTraits<T>::AddRef(aRawPtr);
}
assign_assuming_AddRef(aRawPtr);
}
@ -47,7 +47,7 @@ private:
T* oldPtr = mRawPtr;
mRawPtr = aNewPtr;
if (oldPtr) {
oldPtr->Release();
AddRefTraits<T>::Release(oldPtr);
}
}
@ -60,7 +60,7 @@ public:
~nsRefPtr()
{
if (mRawPtr) {
mRawPtr->Release();
AddRefTraits<T>::Release(mRawPtr);
}
}
@ -77,7 +77,7 @@ public:
// copy-constructor
{
if (mRawPtr) {
mRawPtr->AddRef();
AddRefTraits<T>::AddRef(mRawPtr);
}
}
@ -93,7 +93,7 @@ public:
: mRawPtr(aRawPtr)
{
if (mRawPtr) {
mRawPtr->AddRef();
AddRefTraits<T>::AddRef(mRawPtr);
}
}
@ -111,6 +111,16 @@ public:
{
}
template <typename I>
MOZ_IMPLICIT nsRefPtr(const nsRefPtr<I>& aSmartPtr)
: mRawPtr(aSmartPtr.get())
// copy-construct from a smart pointer with a related pointer type
{
if (mRawPtr) {
AddRefTraits<T>::AddRef(mRawPtr);
}
}
template <typename I>
MOZ_IMPLICIT nsRefPtr(nsRefPtr<I>&& aSmartPtr)
: mRawPtr(aSmartPtr.forget().take())
@ -134,6 +144,15 @@ public:
return *this;
}
template <typename I>
nsRefPtr<T>&
operator=(const nsRefPtr<I>& aRhs)
// assign from an nsRefPtr of a related pointer type
{
assign_with_AddRef(aRhs.get());
return *this;
}
nsRefPtr<T>&
operator=(T* aRhs)
// assign from a raw pointer (of the right type)
@ -307,6 +326,35 @@ public:
assign_assuming_AddRef(0);
return reinterpret_cast<T**>(&mRawPtr);
}
private:
// This helper class makes |nsRefPtr<const T>| possible by casting away
// the constness from the pointer when calling AddRef() and Release().
// This is necessary because AddRef() and Release() implementations can't
// generally expected to be const themselves (without heavy use of |mutable|
// and |const_cast| in their own implementations).
// This should be sound because while |nsRefPtr<const T>| provides a const
// view of an object, the object itself should be const (it would have to be
// allocated as |new const T| or similar to itself be const).
template<class U>
struct AddRefTraits
{
static void AddRef(U* aPtr) {
aPtr->AddRef();
}
static void Release(U* aPtr) {
aPtr->Release();
}
};
template<class U>
struct AddRefTraits<const U>
{
static void AddRef(const U* aPtr) {
const_cast<U*>(aPtr)->AddRef();
}
static void Release(const U* aPtr) {
const_cast<U*>(aPtr)->Release();
}
};
};
class nsCycleCollectionTraversalCallback;

Просмотреть файл

@ -32,6 +32,9 @@ class Foo : public nsISupports
virtual void VirtualConstMemberFunction( int, int*, int& ) const;
static void print_totals();
void NonconstMethod() {}
void ConstMethod() const {}
private:
unsigned int refcount_;
@ -613,8 +616,25 @@ main()
AVoidPtrPtrContext( getter_AddRefs(fooP) );
}
{
printf("\n### setup for Test 25\n");
nsRefPtr<Foo> fooP(new Foo);
printf("\n### Test 25: will a static |nsCOMPtr| |Release| before program termination?\n");
printf("### Test 25: can you construct an |nsRefPtr<const T>| from an |nsRefPtr<T>|?\n");
nsRefPtr<const Foo> constFooP = fooP;
printf("### Test 25: can you call a non-const method on an |nsRefPtr<const T>|?\n");
constFooP->ConstMethod();
// [Shouldn't compile] Is it a compile time error to call a non-const method on an |nsRefPtr<const T>|?
//constFooP->NonconstMethod();
// [Shouldn't compile] Is it a compile time error to construct an |nsRefPtr<T> from an |nsRefPtr<const T>|?
//nsRefPtr<Foo> otherFooP(constFooP);
}
printf("\n### Test 26: will a static |nsCOMPtr| |Release| before program termination?\n");
gFoop = do_QueryObject(new Foo);
{