Bug 1634281 - Pull up GetOrInsertNew to nsBaseHashtable and support other smart pointer types. r=xpcom-reviewers,nika

Differential Revision: https://phabricator.services.mozilla.com/D106486
This commit is contained in:
Simon Giesecke 2021-03-02 09:02:19 +00:00
Родитель f4f7c593e0
Коммит 25331cfdfd
2 изменённых файлов: 86 добавлений и 20 удалений

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

@ -12,13 +12,76 @@
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Result.h"
#include "mozilla/UniquePtr.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsTHashtable.h"
template <class KeyClass, class DataType, class UserDataType, class Converter>
class nsBaseHashtable; // forward declaration
namespace mozilla::detail {
template <typename SmartPtr>
struct SmartPtrTraits {
static constexpr bool IsSmartPointer = false;
static constexpr bool IsRefCounted = false;
};
template <typename Pointee>
struct SmartPtrTraits<UniquePtr<Pointee>> {
static constexpr bool IsSmartPointer = true;
static constexpr bool IsRefCounted = false;
using SmartPointerType = UniquePtr<Pointee>;
using PointeeType = Pointee;
using RawPointerType = Pointee*;
template <typename U>
using OtherSmartPtrType = UniquePtr<U>;
template <typename U, typename... Args>
static SmartPointerType NewObject(Args&&... aConstructionArgs) {
return mozilla::MakeUnique<U>(std::forward<Args>(aConstructionArgs)...);
}
};
template <typename Pointee>
struct SmartPtrTraits<RefPtr<Pointee>> {
static constexpr bool IsSmartPointer = true;
static constexpr bool IsRefCounted = true;
using SmartPointerType = RefPtr<Pointee>;
using PointeeType = Pointee;
using RawPointerType = Pointee*;
template <typename U>
using OtherSmartPtrType = RefPtr<U>;
template <typename U, typename... Args>
static SmartPointerType NewObject(Args&&... aConstructionArgs) {
return MakeRefPtr<U>(std::forward<Args>(aConstructionArgs)...);
}
};
template <typename Pointee>
struct SmartPtrTraits<nsCOMPtr<Pointee>> {
static constexpr bool IsSmartPointer = true;
static constexpr bool IsRefCounted = true;
using SmartPointerType = nsCOMPtr<Pointee>;
using PointeeType = Pointee;
using RawPointerType = Pointee*;
template <typename U>
using OtherSmartPtrType = nsCOMPtr<U>;
template <typename U, typename... Args>
static SmartPointerType NewObject(Args&&... aConstructionArgs) {
return MakeRefPtr<U>(std::forward<Args>(aConstructionArgs)...);
}
};
// XXX Add SafeRefPtr specialization
} // namespace mozilla::detail
/**
* Data type conversion helper that is used to wrap and unwrap the specified
* DataType.
@ -207,6 +270,29 @@ class nsBaseHashtable
return mozilla::Some(Converter::Unwrap(ent->mData));
}
using SmartPtrTraits = mozilla::detail::SmartPtrTraits<DataType>;
/**
* Looks up aKey in the hash table. If it doesn't exist a new object of
* SmartPtrTraits::PointeeType will be created (using the arguments provided)
* and then returned.
*
* \note This can only be instantiated if DataType is a smart pointer.
*/
template <typename... Args>
auto GetOrInsertNew(KeyType aKey, Args&&... aConstructionArgs) {
static_assert(
SmartPtrTraits::IsSmartPointer,
"GetOrInsertNew can only be used with smart pointer data types");
return LookupOrInsertWith(std::move(aKey),
[&] {
return SmartPtrTraits::template NewObject<
typename SmartPtrTraits::PointeeType>(
std::forward<Args>(aConstructionArgs)...);
})
.get();
}
/**
* Add aKey to the table if not already present, and return a reference to its
* value. If aKey is not already in the table then the a default-constructed

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

@ -51,13 +51,6 @@ class nsClassHashtable : public nsBaseHashtable<KeyClass, mozilla::UniquePtr<T>,
nsClassHashtable() = default;
explicit nsClassHashtable(uint32_t aInitLength) : base_type(aInitLength) {}
/**
* Looks up aKey in the hash table. If it doesn't exist a new object of
* KeyClass will be created (using the arguments provided) and then returned.
*/
template <typename... Args>
UserDataType GetOrInsertNew(KeyType aKey, Args&&... aConstructionArgs);
/**
* @copydoc nsBaseHashtable::Get
* @param aData if the key doesn't exist, pData will be set to nullptr.
@ -90,19 +83,6 @@ inline void ImplCycleCollectionTraverse(
// nsClassHashtable definitions
//
template <class KeyClass, class T>
template <typename... Args>
T* nsClassHashtable<KeyClass, T>::GetOrInsertNew(KeyType aKey,
Args&&... aConstructionArgs) {
return this
->LookupOrInsertWith(std::move(aKey),
[&] {
return mozilla::MakeUnique<T>(
std::forward<Args>(aConstructionArgs)...);
})
.get();
}
template <class KeyClass, class T>
bool nsClassHashtable<KeyClass, T>::Get(KeyType aKey, T** aRetVal) const {
typename base_type::EntryType* ent = this->GetEntry(aKey);