зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
f4f7c593e0
Коммит
25331cfdfd
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче