Bug 1923505 - Simplify LinkedList -> nsTArray conversion. r=xpcom-reviewers,hiro,nika

Add a ToTArray version that works with LinkedList.

This is much like what we do for other containers, but without walking the list
twice.

Differential Revision: https://phabricator.services.mozilla.com/D225001
This commit is contained in:
Emilio Cobos Álvarez 2024-10-16 10:32:01 +00:00
parent d8ab308452
commit a79a09ba6d
9 changed files with 53 additions and 43 deletions

View File

@ -40,17 +40,18 @@ AnimationTimeline::~AnimationTimeline() { mAnimationOrder.clear(); }
bool AnimationTimeline::Tick(TickState& aState) {
bool needsTicks = false;
AutoTArray<RefPtr<Animation>, 32> animationsToTick;
#ifdef DEBUG
for (Animation* animation : mAnimationOrder) {
MOZ_ASSERT(mAnimations.Contains(animation),
"The sampling order list should be a subset of the hashset");
MOZ_ASSERT(!animation->IsHiddenByContentVisibility(),
"The sampling order list should not contain any animations "
"that are hidden by content-visibility");
animationsToTick.AppendElement(animation);
}
#endif
for (Animation* animation : animationsToTick) {
for (Animation* animation :
ToTArray<AutoTArray<RefPtr<Animation>, 32>>(mAnimationOrder)) {
// Skip any animations that are longer need associated with this timeline.
if (animation->GetTimeline() != this) {
RemoveAnimation(animation);

View File

@ -160,12 +160,8 @@ void DocumentTimeline::NotifyAnimationUpdated(Animation& aAnimation) {
}
void DocumentTimeline::TriggerAllPendingAnimationsNow() {
AutoTArray<RefPtr<Animation>, 32> animationsToTrigger;
for (Animation* animation : mAnimationOrder) {
animationsToTrigger.AppendElement(animation);
}
for (Animation* animation : animationsToTrigger) {
for (Animation* animation :
ToTArray<AutoTArray<RefPtr<Animation>, 32>>(mAnimationOrder)) {
animation->TryTriggerNow();
}
}

View File

@ -2311,15 +2311,10 @@ void nsRefreshDriver::DetermineProximityToViewportAndNotifyResizeObservers() {
}
static CallState UpdateAndReduceAnimations(Document& aDocument) {
{
AutoTArray<RefPtr<DocumentTimeline>, 32> timelinesToTick;
for (DocumentTimeline* timeline : aDocument.Timelines()) {
timelinesToTick.AppendElement(timeline);
}
for (DocumentTimeline* tl : timelinesToTick) {
tl->WillRefresh();
}
for (DocumentTimeline* tl :
ToTArray<AutoTArray<RefPtr<DocumentTimeline>, 32>>(
aDocument.Timelines())) {
tl->WillRefresh();
}
if (nsPresContext* pc = aDocument.GetPresContext()) {

View File

@ -409,13 +409,13 @@ class LinkedListElement {
template <typename T>
class LinkedList {
private:
typedef typename detail::LinkedListElementTraits<T> Traits;
typedef typename Traits::RawType RawType;
typedef typename Traits::ConstRawType ConstRawType;
typedef typename Traits::ClientType ClientType;
typedef typename Traits::ConstClientType ConstClientType;
typedef LinkedListElement<T>* ElementType;
typedef const LinkedListElement<T>* ConstElementType;
using Traits = typename detail::LinkedListElementTraits<T>;
using RawType = typename Traits::RawType;
using ConstRawType = typename Traits::ConstRawType;
using ClientType = typename Traits::ClientType;
using ConstClientType = typename Traits::ConstClientType;
using ElementType = LinkedListElement<T>*;
using ConstElementType = const LinkedListElement<T>*;
LinkedListElement<T> sentinel;
@ -445,6 +445,9 @@ class LinkedList {
}
};
using const_iterator = Iterator<ConstRawType, ConstElementType>;
using iterator = Iterator<RawType, ElementType>;
LinkedList() : sentinel(LinkedListElement<T>::NodeKind::Sentinel) {}
LinkedList(LinkedList<T>&& aOther) : sentinel(std::move(aOther.sentinel)) {}
@ -701,6 +704,11 @@ class LinkedList {
LinkedList(const LinkedList<T>& aOther) = delete;
};
template <typename T>
size_t RangeSizeEstimate(const LinkedList<T>&) {
return 0;
}
template <typename T>
inline void ImplCycleCollectionUnlink(LinkedList<RefPtr<T>>& aField) {
aField.clear();

View File

@ -30,7 +30,9 @@ template <typename Range, typename AsAtom>
static AtomSet::ArrayType AtomSetFromRange(Range&& aRange,
AsAtom&& aTransform) {
AtomSet::ArrayType atoms;
atoms.SetCapacity(RangeSize(aRange));
if (auto estimate = RangeSizeEstimate(aRange)) {
atoms.SetCapacity(estimate);
}
std::transform(aRange.begin(), aRange.end(), MakeBackInserter(atoms),
std::forward<AsAtom>(aTransform));

View File

@ -175,7 +175,8 @@ class nsBaseHashtableValueRange {
};
template <typename EntryType>
auto RangeSize(const detail::nsBaseHashtableValueRange<EntryType>& aRange) {
size_t RangeSizeEstimate(
const detail::nsBaseHashtableValueRange<EntryType>& aRange) {
return aRange.Count();
}

View File

@ -3274,11 +3274,14 @@ class nsTArrayView {
const Span<element_type> mSpan;
};
template <typename Range, typename = std::enable_if_t<std::is_same_v<
typename std::iterator_traits<
typename Range::iterator>::iterator_category,
std::random_access_iterator_tag>>>
auto RangeSize(const Range& aRange) {
// NOTE(emilio): If changing the name of this or so, make sure to change
// specializations too.
template <typename Range,
typename = std::enable_if_t<std::is_same_v<
typename std::iterator_traits<typename std::remove_reference_t<
Range>::iterator>::iterator_category,
std::random_access_iterator_tag>>>
size_t RangeSizeEstimate(const Range& aRange) {
// See https://en.cppreference.com/w/cpp/iterator/begin, section 'User-defined
// overloads'.
using std::begin;
@ -3293,12 +3296,14 @@ auto RangeSize(const Range& aRange) {
* convertible from the range's value type.
*/
template <typename Array, typename Range>
auto ToTArray(const Range& aRange) {
auto ToTArray(Range&& aRange) {
using std::begin;
using std::end;
Array res;
res.SetCapacity(RangeSize(aRange));
if (auto estimate = RangeSizeEstimate(aRange)) {
res.SetCapacity(estimate);
}
std::copy(begin(aRange), end(aRange), MakeBackInserter(res));
return res;
}
@ -3307,21 +3312,22 @@ auto ToTArray(const Range& aRange) {
* Materialize a range as a nsTArray of its (decayed) value type.
*/
template <typename Range>
auto ToArray(const Range& aRange) {
return ToTArray<nsTArray<std::decay_t<
typename std::iterator_traits<typename Range::iterator>::value_type>>>(
aRange);
auto ToArray(Range&& aRange) {
return ToTArray<nsTArray<std::decay_t<typename std::iterator_traits<
typename std::remove_reference_t<Range>::iterator>::value_type>>>(
std::forward<Range>(aRange));
}
/**
* Appends all elements from a range to an array.
*/
template <typename Array, typename Range>
void AppendToArray(Array& aArray, const Range& aRange) {
void AppendToArray(Array& aArray, Range&& aRange) {
using std::begin;
using std::end;
aArray.SetCapacity(aArray.Length() + RangeSize(aRange));
if (auto estimate = RangeSizeEstimate(aRange)) {
aArray.SetCapacity(aArray.Length() + estimate);
}
std::copy(begin(aRange), end(aRange), MakeBackInserter(aArray));
}

View File

@ -134,7 +134,7 @@ class nsTBaseHashSet : protected nsTHashtable<KeyClass> {
};
template <typename KeyClass>
auto RangeSize(const nsTBaseHashSet<KeyClass>& aRange) {
size_t RangeSizeEstimate(const nsTBaseHashSet<KeyClass>& aRange) {
return aRange.Count();
}

View File

@ -168,7 +168,8 @@ class nsTHashtableKeyRange {
};
template <typename EntryType>
auto RangeSize(const ::detail::nsTHashtableKeyRange<EntryType>& aRange) {
size_t RangeSizeEstimate(
const ::detail::nsTHashtableKeyRange<EntryType>& aRange) {
return aRange.Count();
}