diff --git a/applications/test/PtrList/Test-PtrList.cxx b/applications/test/PtrList/Test-PtrList.cxx index 2df2c5cbf0..88c8cfbffe 100644 --- a/applications/test/PtrList/Test-PtrList.cxx +++ b/applications/test/PtrList/Test-PtrList.cxx @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011 OpenFOAM Foundation - Copyright (C) 2018-2023 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -86,20 +86,7 @@ Ostream& printAddr const UPtrList& list ) { - const label len = list.size(); - - // Size and start delimiter - os << nl << indent << len << nl - << indent << token::BEGIN_LIST << incrIndent << nl; - - for (label i=0; i < len; ++i) - { - os << "addr=" << Foam::name(list.get(i)) << nl; - } - - // End delimiter - os << decrIndent << indent << token::END_LIST << nl; - return os; + return list.printAddresses(os); } @@ -176,11 +163,11 @@ Ostream& print { const label cap = list.capacity(); - for (label i=len; i < cap; ++i) + for (label i = len; i < cap; ++i) { const T* ptr = list.get(i); - os << "unused " << name(ptr) << nl; + os << "unused " << Foam::name(ptr) << nl; } } @@ -518,6 +505,7 @@ int main(int argc, char *argv[]) print(Info, dynlist1d); Info<< "addresses:" << nl; + dynlist1d.printAddresses(Info, true); printAddr(Info, dynlist1d); PtrList list1d; diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H index 002610037f..92932c92ba 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H @@ -255,7 +255,7 @@ public: // Edit //- Swap with plain List content. Implies shrink_to_fit(). - inline void swap(List& list); + inline void swap(List& other); //- Swap content, independent of sizing parameter template @@ -264,7 +264,7 @@ public: //- Transfer contents of the argument List into this. inline void transfer(List& list); - //- Transfer contents of any sized DynamicList into this. + //- Transfer contents of any DynamicList into this. template inline void transfer(DynamicList& list); diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H index d452f52d7d..ed94ae38b4 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H @@ -445,6 +445,8 @@ inline void Foam::DynamicList::clear() noexcept template inline void Foam::DynamicList::clearStorage() { + // Consistent allocated sizing + List::setAddressableSize(capacity_); List::clear(); capacity_ = 0; } @@ -465,12 +467,15 @@ inline void Foam::DynamicList::shrink_to_fit() template inline void -Foam::DynamicList::swap(List& list) +Foam::DynamicList::swap(List& other) { if ( - static_cast*>(this) - == static_cast*>(&list) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&other) + ) ) { return; // Self-swap is a no-op @@ -480,7 +485,7 @@ Foam::DynamicList::swap(List& list) this->shrink_to_fit(); // Swap storage and addressable size - UList::swap(list); + UList::swap(other); // Update capacity capacity_ = List::size(); @@ -496,8 +501,11 @@ inline void Foam::DynamicList::swap { if ( - static_cast*>(this) - == static_cast*>(&other) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&other) + ) ) { return; // Self-swap is a no-op @@ -515,6 +523,10 @@ template inline void Foam::DynamicList::transfer(List& list) { + // No check for self-assignment (different types) + + // Consistent allocated sizing + List::setAddressableSize(capacity_); List::transfer(list); capacity_ = List::size(); } @@ -530,18 +542,22 @@ Foam::DynamicList::transfer { if ( - static_cast*>(this) - == static_cast*>(&list) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) ) { return; // Self-assignment is a no-op } - // Take over storage as-is (without shrink) - capacity_ = list.capacity(); - + // Consistent allocated sizing + List::setAddressableSize(capacity_); List::transfer(static_cast&>(list)); - list.clearStorage(); // capacity=0 etc. + + capacity_ = list.capacity(); + list.setCapacity_unsafe(0); // All contents moved } @@ -594,7 +610,14 @@ inline void Foam::DynamicList::push_back const UList& list ) { - if (FOAM_UNLIKELY(this == &list)) + if + ( + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) + ) { FatalErrorInFunction << "Attempted push_back to self" @@ -665,7 +688,14 @@ inline void Foam::DynamicList::push_back List&& list ) { - if (FOAM_UNLIKELY(this == &list)) + if + ( + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) + ) { FatalErrorInFunction << "Attempted push_back to self" @@ -675,6 +705,7 @@ inline void Foam::DynamicList::push_back const label idx = List::size(); resize(idx + list.size()); + // Move the elements std::move(list.begin(), list.end(), this->begin(idx)); list.clear(); @@ -688,7 +719,26 @@ inline void Foam::DynamicList::push_back DynamicList&& list ) { - push_back(std::move(static_cast&>(list))); + if + ( + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) + ) + { + FatalErrorInFunction + << "Attempted push_back to self" + << abort(FatalError); + } + + const label idx = List::size(); + resize(idx + list.size()); + + // Move the elements + std::move(list.begin(), list.end(), this->begin(idx)); + list.clearStorage(); // Deletion, capacity=0 etc. } @@ -866,15 +916,22 @@ inline void Foam::DynamicList::operator= template inline void Foam::DynamicList::operator= ( - const DynamicList& lst + const DynamicList& list ) { - if (this == &lst) + if + ( + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) + ) { return; // Self-assignment is a no-op } - doAssignDynList(lst); + doAssignDynList(list); } @@ -887,8 +944,11 @@ inline void Foam::DynamicList::operator= { if ( - static_cast*>(this) - == static_cast*>(&list) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) ) { return; // Self-assignment is a no-op @@ -912,44 +972,41 @@ template template inline void Foam::DynamicList::operator= ( - const IndirectListBase& lst + const IndirectListBase& list ) { // NOTE: Self-assignment needs special handling - /// if - /// ( - /// static_cast*>(this) - /// == static_cast*>(&list.values()) - /// ) + // if + // ( + // FOAM_UNLIKELY + // ( + // static_cast*>(this) + // == static_cast*>(&list.values()) + // ) + // ) + // { ... } - doAssignDynList(lst); + doAssignDynList(list); } template inline void Foam::DynamicList::operator= ( - List&& lst + List&& list ) { - clear(); - transfer(lst); + this->transfer(list); } template inline void Foam::DynamicList::operator= ( - DynamicList&& lst + DynamicList&& list ) { - if (this == &lst) - { - return; // Self-assignment is a no-op - } - - clear(); - transfer(lst); + this->transfer(list); } @@ -960,17 +1017,7 @@ inline void Foam::DynamicList::operator= DynamicList&& list ) { - if - ( - static_cast*>(this) - == static_cast*>(&list) - ) - { - return; // Self-assignment is a no-op - } - - clear(); - transfer(list); + this->transfer(list); } diff --git a/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynList.H b/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynList.H index d7f202e838..c0f47c88ca 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynList.H +++ b/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynList.H @@ -238,14 +238,18 @@ public: //- Auto-sizes list as required. inline autoPtr set(const label i, const tmp& ptr); - //- Reorder elements. Reordering must be unique (ie, shuffle). - inline void reorder(const labelUList& oldToNew); + + // Writing + + //- Print pointer addresses to Ostream (debugging only). + // Optionally print addresses within the upper (capacity) region + Ostream& printAddresses(Ostream& os, const bool full=false) const; // Member Operators //- Copy (clone) assignment - inline void operator=(const PtrList& list); + inline void operator=(const UPtrList& list); //- Copy (clone) assignment inline void operator=(const PtrDynList& list); diff --git a/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynListI.H b/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynListI.H index 03be2398f4..c61b342232 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynListI.H +++ b/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynListI.H @@ -226,6 +226,8 @@ inline void Foam::PtrDynList::clear() template inline void Foam::PtrDynList::clearStorage() { + // Consistent allocated sizing + PtrList::setAddressableSize(capacity_); PtrList::clear(); capacity_ = 0; } @@ -258,8 +260,11 @@ inline void Foam::PtrDynList::swap(PtrList& list) { if ( - static_cast*>(this) - == static_cast*>(&list) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) ) { return; // Self-swap is a no-op @@ -285,8 +290,11 @@ inline void Foam::PtrDynList::swap { if ( - static_cast*>(this) - == static_cast*>(&other) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&other) + ) ) { return; // Self-swap is a no-op @@ -303,15 +311,10 @@ inline void Foam::PtrDynList::swap template inline void Foam::PtrDynList::transfer(PtrList& list) { - if - ( - static_cast*>(this) - == static_cast*>(&list) - ) - { - return; // Self assignment is a no-op - } + // No check for self-assignment (different types) + // Consistent allocated sizing + PtrList::setAddressableSize(capacity_); PtrList::transfer(list); capacity_ = PtrList::size(); } @@ -326,18 +329,22 @@ inline void Foam::PtrDynList::transfer { if ( - static_cast*>(this) - == static_cast*>(&list) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) ) { return; // Self assignment is a no-op } - // Take over storage as-is (without shrink) - capacity_ = list.capacity(); - + // Consistent allocated sizing + PtrList::setAddressableSize(capacity_); PtrList::transfer(static_cast&>(list)); - list.clearStorage(); // capacity=0 etc. + + capacity_ = list.capacity(); + list.setCapacity_unsafe(0); // All contents moved } @@ -414,8 +421,11 @@ inline void Foam::PtrDynList::push_back { if ( - static_cast*>(this) - == static_cast*>(&other) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&other) + ) ) { FatalErrorInFunction @@ -557,11 +567,20 @@ inline Foam::autoPtr Foam::PtrDynList::set template -inline void Foam::PtrDynList::reorder(const labelUList& oldToNew) +Foam::Ostream& Foam::PtrDynList::printAddresses +( + Ostream& os, + const bool full +) const { - // Shrinking first is a bit annoying, but saves needing a special version. - this->shrink_to_fit(); - PtrList::reorder(oldToNew); + if (full) + { + return this->ptrs_.printAddresses(os, capacity_); + } + else + { + return UPtrList::printAddresses(os); + } } @@ -570,16 +589,23 @@ inline void Foam::PtrDynList::reorder(const labelUList& oldToNew) template inline void Foam::PtrDynList::operator= ( - const PtrList& list + const UPtrList& list ) { - if (this == &list) + if + ( + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) + ) { return; // Self-assignment is a no-op } + this->resize(list.size()); PtrList::operator=(list); - capacity_ = PtrList::size(); } @@ -589,13 +615,20 @@ inline void Foam::PtrDynList::operator= const PtrDynList& list ) { - if (this == &list) + if + ( + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) + ) { return; // Self-assignment is a no-op } - PtrList::operator=(list); - capacity_ = PtrList::size(); + this->resize(list.size()); + PtrList::operator=(static_cast&>(list)); } @@ -608,14 +641,18 @@ inline void Foam::PtrDynList::operator= { if ( - static_cast*>(this) - == static_cast*>(&list) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) ) { return; // Self-assignment is a no-op } - PtrList::operator=(list); + this->resize(list.size()); + PtrList::operator=(static_cast&>(list)); capacity_ = PtrList::size(); } diff --git a/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.C b/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.C index 9b082f4940..52f8b420be 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.C +++ b/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018-2019 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,26 +29,55 @@ License #include "PtrList.H" #include "SLPtrList.H" -// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template -Foam::PtrList::PtrList(PtrList& list, bool reuse) -: - UPtrList(list, reuse) +template +void Foam::PtrList::copyPtrList(const UPtrList& list) { - if (!reuse) + // Check for self-assignment here instead of caller + if constexpr (CheckSelf) { - // This works like an inplace clone method - const label len = this->size(); - - for (label i=0; iptrs_[i] = (list[i]).clone().ptr(); + return; // Self-assignment is a no-op + } + } + + const label len = list.size(); + + // Truncate (frees old pointers) or extend the length + PtrList::resize(len); + + for (label i = 0; i < len; ++i) + { + const T* src = list.get(i); + + if (src) + { + if (this->ptrs_[i]) + { + // Deep copy values into existing destination + *(this->ptrs_[i]) = *src; + } + else + { + // Clone pointers for new entries + this->ptrs_[i] = src->clone().ptr(); + } + } + else + { + // No source pointer, so remove destination (if any) too + delete this->ptrs_[i]; + this->ptrs_[i] = nullptr; } } } +// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // + template Foam::PtrList::PtrList(const SLPtrList& list) : @@ -122,45 +151,4 @@ void Foam::PtrList::resize(const label newLen) } -// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // - -template -void Foam::PtrList::operator=(const PtrList& list) -{ - if (this == &list) - { - return; // Self-assignment is a no-op - } - - const label oldLen = this->size(); - const label newLen = list.size(); - - // Truncate (frees old pointers) or extend the length - resize(newLen); - - if (newLen < oldLen) - { - // Copy values for existing entries - for (label i=0; iptrs_[i] = (list[i]).clone().ptr(); - } - } -} - - // ************************************************************************* // diff --git a/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H b/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H index 89e4a9688a..c0f4def07e 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H +++ b/src/OpenFOAM/containers/PtrLists/PtrList/PtrList.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018-2023 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -70,6 +70,15 @@ class PtrList : public UPtrList { + // Private Member Functions + + //- Copy assignment. + // For existing list entries, values are copied from the list. + // For new list entries, pointers are cloned from the list. + template + void copyPtrList(const UPtrList& list); + + protected: // Protected Member Functions @@ -103,7 +112,7 @@ public: inline PtrList(const PtrList& list, const CloneArg& cloneArgs); //- Construct as copy or re-use as specified - PtrList(PtrList& list, bool reuse); + inline PtrList(PtrList& list, bool reuse); //- Copy construct using 'clone()' on each element of SLPtrList\ explicit PtrList(const SLPtrList& list); @@ -221,6 +230,11 @@ public: // Member Operators + //- Copy assignment. + // For existing list entries, values are copied from the list. + // For new list entries, pointers are cloned from the list. + void operator=(const UPtrList& list); + //- Copy assignment. // For existing list entries, values are copied from the list. // For new list entries, pointers are cloned from the list. diff --git a/src/OpenFOAM/containers/PtrLists/PtrList/PtrListI.H b/src/OpenFOAM/containers/PtrLists/PtrList/PtrListI.H index 7db0496d3b..49f8766dd9 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrList/PtrListI.H +++ b/src/OpenFOAM/containers/PtrLists/PtrList/PtrListI.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018-2023 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -60,6 +60,23 @@ inline Foam::PtrList::PtrList(PtrList&& list) noexcept {} +template +inline Foam::PtrList::PtrList(PtrList& list, bool reuse) +: + UPtrList() +{ + if (reuse) + { + transfer(list); + } + else + { + // No check for self-assignment + copyPtrList(list); + } +} + + template inline Foam::PtrList::PtrList(UList& list) : @@ -278,7 +295,7 @@ inline Foam::autoPtr Foam::PtrList::release(const label i) template inline void Foam::PtrList::transfer(PtrList& list) { - if (this == &list) + if (FOAM_UNLIKELY(this == &list)) { return; // Self-assignment is a no-op } @@ -290,6 +307,22 @@ inline void Foam::PtrList::transfer(PtrList& list) // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // +template +inline void Foam::PtrList::operator=(const UPtrList& list) +{ + // With check for self-assignment + this->copyPtrList(list); +} + + +template +inline void Foam::PtrList::operator=(const PtrList& list) +{ + // With check for self-assignment + this->copyPtrList(list); +} + + template inline void Foam::PtrList::operator=(PtrList&& list) { diff --git a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C index c0917472a4..1f324116c0 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C +++ b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2024 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -99,11 +99,10 @@ Foam::label Foam::Detail::PtrListDetail::find_next_not(label pos) const template void Foam::Detail::PtrListDetail::free() { - List& ptrs = *this; - const label len = ptrs.size(); - // Presume they were allocated from front to back... - for (label i = len - 1; i >= 0; --i) + List& ptrs = *this; + + for (auto i = this->size()-1; i >= 0; --i) { delete ptrs[i]; ptrs[i] = nullptr; diff --git a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H index cc78942272..bd7983a3bf 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H +++ b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2024 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -147,6 +147,10 @@ public: // Use with care inline void setAddressableSize(const label n) noexcept; + //- Write pointer values to Ostream (debugging only). + // Optionally allow addressing beyond the regular range + Ostream& printAddresses(Ostream& os, label maxLen = -1) const; + //- Write output, optionally silently trimming nullptrs Ostream& write(Ostream& os, const bool trimNull=false) const; diff --git a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetailIO.C b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetailIO.C index f3713841d9..558f3394bd 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetailIO.C +++ b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetailIO.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2024 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,6 +31,45 @@ License // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template +Foam::Ostream& Foam::Detail::PtrListDetail::printAddresses +( + Ostream& os, + label maxLen +) const +{ + if (maxLen <= 0) + { + maxLen = this->size(); + } + + const label len = Foam::min(this->size(), maxLen); + + // The (output) size and start delimiter + os << nl << indent << maxLen << nl + << indent << token::BEGIN_LIST << nl; + + // const T* const * iter = this->cdata(); + const auto* iter = this->cdata(); + + // Contents + for (label i = 0; i < len; ++i) + { + os << indent << " " << Foam::name(iter[i]) << nl; + } + for (label i = len; i < maxLen; ++i) + { + os << indent << " [" << Foam::name(iter[i]) << ']' << nl; + } + + // End delimiter + os << indent << token::END_LIST << nl; + + os.check(FUNCTION_NAME); + return os; +} + + template Foam::Ostream& Foam::Detail::PtrListDetail::write ( diff --git a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.C b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.C index 77b06feec8..396a027e4c 100644 --- a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.C +++ b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -65,23 +65,6 @@ Foam::label Foam::UPtrList::squeezeNull() } -template -void Foam::UPtrList::trimTrailingNull() -{ - label newLen = this->size(); - - for (label i = newLen-1; i >= 0 && !ptrs_[i]; --i) - { - --newLen; - } - - // Or mutable? - // const_cast&>(ptrs_).setAddressableSize(newLen); - - ptrs_.setAddressableSize(newLen); -} - - template void Foam::UPtrList::reorder(const labelUList& oldToNew, const bool check) { @@ -98,7 +81,7 @@ void Foam::UPtrList::reorder(const labelUList& oldToNew, const bool check) Detail::PtrListDetail newList(len); - for (label i=0; i::reorder(const labelUList& oldToNew, const bool check) newList.checkNonNull(); } - ptrs_.transfer(newList); + // Copy the pointers, do not swap or transfer lists! + ptrs_ = newList; } @@ -148,7 +132,7 @@ void Foam::UPtrList::sortOrder(const labelUList& order, const bool check) Detail::PtrListDetail newList(len); Detail::PtrListDetail guard(len); - for (label i=0; i::sortOrder(const labelUList& order, const bool check) newList.checkNonNull(); } - ptrs_.transfer(newList); + // Copy the pointers, do not swap or transfer lists! + ptrs_ = newList; } // * * * * * * * * * * * * * * * Ostream Operators * * * * * * * * * * * * * // +template +Foam::Ostream& Foam::UPtrList::printAddresses(Ostream& os) const +{ + return ptrs_.printAddresses(os); +} + + +template +Foam::Ostream& Foam::UPtrList::writeList +( + Ostream& os, + const bool trimNull +) const +{ + return ptrs_.write(os, trimNull); +} + + template Foam::Ostream& Foam::operator<<(Ostream& os, const UPtrList& list) { - return list.ptrs_.write(os); + return list.writeList(os, false); // Do not ignore null } diff --git a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H index 4ab765d034..75161187cb 100644 --- a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H +++ b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H @@ -314,10 +314,6 @@ public: // \return the number of non-null entries label squeezeNull(); - //- Reduce addressable list size to ignore any trailing null pointers. - // The reduces the effective list length without reallocation - void trimTrailingNull(); - //- Append an element to the end of the list inline void push_back(T* ptr); @@ -382,9 +378,18 @@ public: inline void operator=(UPtrList&& list); + // Writing + + //- Print pointer addresses to Ostream (debugging only) + Ostream& printAddresses(Ostream& os) const; + + //- Write UPtrList to Ostream, optionally ignoring null entries + Ostream& writeList(Ostream& os, const bool trimNull=false) const; + + // IOstream Operators - //- Write UPtrList to Ostream + //- Write UPtrList to Ostream. Does not ignore null entries friend Ostream& operator<< (Ostream& os, const UPtrList& list); diff --git a/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H b/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H index c161fc327c..5679ca5b9c 100644 --- a/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H +++ b/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H @@ -269,7 +269,7 @@ public: // Edit //- Swap with plain List content. Implies shrink_to_fit(). - inline void swap(List& list); + inline void swap(List& other); //- Swap content, independent of sizing parameter template diff --git a/src/OpenFOAM/fields/Fields/DynamicField/DynamicFieldI.H b/src/OpenFOAM/fields/Fields/DynamicField/DynamicFieldI.H index ec9237be50..67ced92b34 100644 --- a/src/OpenFOAM/fields/Fields/DynamicField/DynamicFieldI.H +++ b/src/OpenFOAM/fields/Fields/DynamicField/DynamicFieldI.H @@ -567,12 +567,12 @@ inline void Foam::DynamicField::shrink_to_fit() template inline void -Foam::DynamicField::swap(List& list) +Foam::DynamicField::swap(List& other) { if ( static_cast*>(this) - == static_cast*>(&list) + == static_cast*>(&other) ) { return; // Self-swap is a no-op @@ -582,7 +582,7 @@ Foam::DynamicField::swap(List& list) this->shrink_to_fit(); // Swap storage and addressable size - UList::swap(list); + UList::swap(other); // Update capacity capacity_ = List::size(); @@ -658,17 +658,22 @@ inline void Foam::DynamicField::transfer { if ( - static_cast*>(this) - == static_cast*>(&list) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) ) { return; // Self-assignment is a no-op } - // Take over storage as-is (without shrink) - capacity_ = list.capacity(); + // Consistent allocated sizing + List::setAddressableSize(capacity_); Field::transfer(static_cast&>(list)); - list.clearStorage(); // capacity=0 etc. + + capacity_ = list.capacity(); + list.setCapacity_unsafe(0); // All contents moved } @@ -681,17 +686,22 @@ inline void Foam::DynamicField::transfer { if ( - static_cast*>(this) - == static_cast*>(&list) + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) ) { return; // Self-assignment is a no-op } - // Take over storage as-is (without shrink) - capacity_ = list.capacity(); + // Consistent allocated sizing + List::setAddressableSize(capacity_); Field::transfer(static_cast&>(list)); - list.clearStorage(); // capacity=0 etc. + + capacity_ = list.capacity(); + list.setCapacity_unsafe(0); // All contents moved } @@ -744,7 +754,14 @@ inline void Foam::DynamicField::push_back const UList& list ) { - if (this == &list) + if + ( + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) + ) { FatalErrorInFunction << "Attempted push_back to self" @@ -764,7 +781,14 @@ inline void Foam::DynamicField::push_back List&& list ) { - if (this == &list) + if + ( + FOAM_UNLIKELY + ( + static_cast*>(this) + == static_cast*>(&list) + ) + ) { FatalErrorInFunction << "Attempted push_back to self" @@ -774,6 +798,7 @@ inline void Foam::DynamicField::push_back const label idx = List::size(); resize(idx + list.size()); + // Move the elements std::move(list.begin(), list.end(), this->begin(idx)); list.clear(); @@ -880,7 +905,7 @@ inline void Foam::DynamicField::operator= List&& list ) { - transfer(list); + this->transfer(list); } @@ -890,7 +915,7 @@ inline void Foam::DynamicField::operator= DynamicField&& list ) { - transfer(list); + this->transfer(list); } @@ -901,7 +926,7 @@ inline void Foam::DynamicField::operator= DynamicField&& list ) { - transfer(list); + this->transfer(list); } @@ -912,7 +937,7 @@ inline void Foam::DynamicField::operator= DynamicList&& list ) { - transfer(list); + this->transfer(list); }