mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-12-28 03:37:59 +00:00
ENH: improved handling of PtrList copies/cloning
- the logic has been revised to allow list copying with nullptr entries. These previously would have thrown an error. - remove PtrList trimTrailingNull() method. It was unused and would result in inconsistent addressing sizes. FIX: inconsistent sizing used for DynamicList/PtrDynList clearStorage() - older code did not reset addressable size prior to clearStorage() or transfer(). Only a latent bug until memory pools are used.
This commit is contained in:
@ -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<T>& 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<Scalar> list1d;
|
||||
|
||||
@ -255,7 +255,7 @@ public:
|
||||
// Edit
|
||||
|
||||
//- Swap with plain List content. Implies shrink_to_fit().
|
||||
inline void swap(List<T>& list);
|
||||
inline void swap(List<T>& other);
|
||||
|
||||
//- Swap content, independent of sizing parameter
|
||||
template<int AnySizeMin>
|
||||
@ -264,7 +264,7 @@ public:
|
||||
//- Transfer contents of the argument List into this.
|
||||
inline void transfer(List<T>& list);
|
||||
|
||||
//- Transfer contents of any sized DynamicList into this.
|
||||
//- Transfer contents of any DynamicList into this.
|
||||
template<int AnySizeMin>
|
||||
inline void transfer(DynamicList<T, AnySizeMin>& list);
|
||||
|
||||
|
||||
@ -445,6 +445,8 @@ inline void Foam::DynamicList<T, SizeMin>::clear() noexcept
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::clearStorage()
|
||||
{
|
||||
// Consistent allocated sizing
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
List<T>::clear();
|
||||
capacity_ = 0;
|
||||
}
|
||||
@ -465,12 +467,15 @@ inline void Foam::DynamicList<T, SizeMin>::shrink_to_fit()
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void
|
||||
Foam::DynamicList<T, SizeMin>::swap(List<T>& list)
|
||||
Foam::DynamicList<T, SizeMin>::swap(List<T>& other)
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&other)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-swap is a no-op
|
||||
@ -480,7 +485,7 @@ Foam::DynamicList<T, SizeMin>::swap(List<T>& list)
|
||||
this->shrink_to_fit();
|
||||
|
||||
// Swap storage and addressable size
|
||||
UList<T>::swap(list);
|
||||
UList<T>::swap(other);
|
||||
|
||||
// Update capacity
|
||||
capacity_ = List<T>::size();
|
||||
@ -496,8 +501,11 @@ inline void Foam::DynamicList<T, SizeMin>::swap
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&other)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&other)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-swap is a no-op
|
||||
@ -515,6 +523,10 @@ template<class T, int SizeMin>
|
||||
inline void
|
||||
Foam::DynamicList<T, SizeMin>::transfer(List<T>& list)
|
||||
{
|
||||
// No check for self-assignment (different types)
|
||||
|
||||
// Consistent allocated sizing
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
List<T>::transfer(list);
|
||||
capacity_ = List<T>::size();
|
||||
}
|
||||
@ -530,18 +542,22 @@ Foam::DynamicList<T, SizeMin>::transfer
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
|
||||
// Take over storage as-is (without shrink)
|
||||
capacity_ = list.capacity();
|
||||
|
||||
// Consistent allocated sizing
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
List<T>::transfer(static_cast<List<T>&>(list));
|
||||
list.clearStorage(); // capacity=0 etc.
|
||||
|
||||
capacity_ = list.capacity();
|
||||
list.setCapacity_unsafe(0); // All contents moved
|
||||
}
|
||||
|
||||
|
||||
@ -594,7 +610,14 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
|
||||
const UList<T>& list
|
||||
)
|
||||
{
|
||||
if (FOAM_UNLIKELY(this == &list))
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted push_back to self"
|
||||
@ -665,7 +688,14 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
|
||||
List<T>&& list
|
||||
)
|
||||
{
|
||||
if (FOAM_UNLIKELY(this == &list))
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted push_back to self"
|
||||
@ -675,6 +705,7 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
|
||||
const label idx = List<T>::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<T, SizeMin>::push_back
|
||||
DynamicList<T, AnySizeMin>&& list
|
||||
)
|
||||
{
|
||||
push_back(std::move(static_cast<List<T>&>(list)));
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted push_back to self"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
const label idx = List<T>::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<T, SizeMin>::operator=
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::operator=
|
||||
(
|
||||
const DynamicList<T, SizeMin>& lst
|
||||
const DynamicList<T, SizeMin>& list
|
||||
)
|
||||
{
|
||||
if (this == &lst)
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
|
||||
doAssignDynList(lst);
|
||||
doAssignDynList(list);
|
||||
}
|
||||
|
||||
|
||||
@ -887,8 +944,11 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
@ -912,44 +972,41 @@ template<class T, int SizeMin>
|
||||
template<class Addr>
|
||||
inline void Foam::DynamicList<T, SizeMin>::operator=
|
||||
(
|
||||
const IndirectListBase<T, Addr>& lst
|
||||
const IndirectListBase<T, Addr>& list
|
||||
)
|
||||
{
|
||||
// NOTE: Self-assignment needs special handling
|
||||
/// if
|
||||
/// (
|
||||
/// static_cast<const UList<T>*>(this)
|
||||
/// == static_cast<const UList<T>*>(&list.values())
|
||||
/// )
|
||||
// if
|
||||
// (
|
||||
// FOAM_UNLIKELY
|
||||
// (
|
||||
// static_cast<const UList<T>*>(this)
|
||||
// == static_cast<const UList<T>*>(&list.values())
|
||||
// )
|
||||
// )
|
||||
// { ... }
|
||||
|
||||
doAssignDynList(lst);
|
||||
doAssignDynList(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::operator=
|
||||
(
|
||||
List<T>&& lst
|
||||
List<T>&& list
|
||||
)
|
||||
{
|
||||
clear();
|
||||
transfer(lst);
|
||||
this->transfer(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::operator=
|
||||
(
|
||||
DynamicList<T, SizeMin>&& lst
|
||||
DynamicList<T, SizeMin>&& 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<T, SizeMin>::operator=
|
||||
DynamicList<T, AnySizeMin>&& list
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
|
||||
clear();
|
||||
transfer(list);
|
||||
this->transfer(list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -238,14 +238,18 @@ public:
|
||||
//- Auto-sizes list as required.
|
||||
inline autoPtr<T> set(const label i, const tmp<T>& 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<T>& list);
|
||||
inline void operator=(const UPtrList<T>& list);
|
||||
|
||||
//- Copy (clone) assignment
|
||||
inline void operator=(const PtrDynList<T, SizeMin>& list);
|
||||
|
||||
@ -226,6 +226,8 @@ inline void Foam::PtrDynList<T, SizeMin>::clear()
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::PtrDynList<T, SizeMin>::clearStorage()
|
||||
{
|
||||
// Consistent allocated sizing
|
||||
PtrList<T>::setAddressableSize(capacity_);
|
||||
PtrList<T>::clear();
|
||||
capacity_ = 0;
|
||||
}
|
||||
@ -258,8 +260,11 @@ inline void Foam::PtrDynList<T, SizeMin>::swap(PtrList<T>& list)
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&list)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-swap is a no-op
|
||||
@ -285,8 +290,11 @@ inline void Foam::PtrDynList<T, SizeMin>::swap
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&other)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&other)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-swap is a no-op
|
||||
@ -303,15 +311,10 @@ inline void Foam::PtrDynList<T, SizeMin>::swap
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::PtrDynList<T, SizeMin>::transfer(PtrList<T>& list)
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&list)
|
||||
)
|
||||
{
|
||||
return; // Self assignment is a no-op
|
||||
}
|
||||
// No check for self-assignment (different types)
|
||||
|
||||
// Consistent allocated sizing
|
||||
PtrList<T>::setAddressableSize(capacity_);
|
||||
PtrList<T>::transfer(list);
|
||||
capacity_ = PtrList<T>::size();
|
||||
}
|
||||
@ -326,18 +329,22 @@ inline void Foam::PtrDynList<T, SizeMin>::transfer
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&list)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self assignment is a no-op
|
||||
}
|
||||
|
||||
// Take over storage as-is (without shrink)
|
||||
capacity_ = list.capacity();
|
||||
|
||||
// Consistent allocated sizing
|
||||
PtrList<T>::setAddressableSize(capacity_);
|
||||
PtrList<T>::transfer(static_cast<PtrList<T>&>(list));
|
||||
list.clearStorage(); // capacity=0 etc.
|
||||
|
||||
capacity_ = list.capacity();
|
||||
list.setCapacity_unsafe(0); // All contents moved
|
||||
}
|
||||
|
||||
|
||||
@ -414,8 +421,11 @@ inline void Foam::PtrDynList<T, SizeMin>::push_back
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&other)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&other)
|
||||
)
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
@ -557,11 +567,20 @@ inline Foam::autoPtr<T> Foam::PtrDynList<T, SizeMin>::set
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::PtrDynList<T, SizeMin>::reorder(const labelUList& oldToNew)
|
||||
Foam::Ostream& Foam::PtrDynList<T, SizeMin>::printAddresses
|
||||
(
|
||||
Ostream& os,
|
||||
const bool full
|
||||
) const
|
||||
{
|
||||
// Shrinking first is a bit annoying, but saves needing a special version.
|
||||
this->shrink_to_fit();
|
||||
PtrList<T>::reorder(oldToNew);
|
||||
if (full)
|
||||
{
|
||||
return this->ptrs_.printAddresses(os, capacity_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return UPtrList<T>::printAddresses(os);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -570,16 +589,23 @@ inline void Foam::PtrDynList<T, SizeMin>::reorder(const labelUList& oldToNew)
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::PtrDynList<T, SizeMin>::operator=
|
||||
(
|
||||
const PtrList<T>& list
|
||||
const UPtrList<T>& list
|
||||
)
|
||||
{
|
||||
if (this == &list)
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const UPtrList<T>*>(this)
|
||||
== static_cast<const UPtrList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
|
||||
this->resize(list.size());
|
||||
PtrList<T>::operator=(list);
|
||||
capacity_ = PtrList<T>::size();
|
||||
}
|
||||
|
||||
|
||||
@ -589,13 +615,20 @@ inline void Foam::PtrDynList<T, SizeMin>::operator=
|
||||
const PtrDynList<T, SizeMin>& list
|
||||
)
|
||||
{
|
||||
if (this == &list)
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const UPtrList<T>*>(this)
|
||||
== static_cast<const UPtrList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
|
||||
PtrList<T>::operator=(list);
|
||||
capacity_ = PtrList<T>::size();
|
||||
this->resize(list.size());
|
||||
PtrList<T>::operator=(static_cast<UPtrList<T>&>(list));
|
||||
}
|
||||
|
||||
|
||||
@ -608,14 +641,18 @@ inline void Foam::PtrDynList<T, SizeMin>::operator=
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&list)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const PtrList<T>*>(this)
|
||||
== static_cast<const PtrList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
|
||||
PtrList<T>::operator=(list);
|
||||
this->resize(list.size());
|
||||
PtrList<T>::operator=(static_cast<UPtrList<T>&>(list));
|
||||
capacity_ = PtrList<T>::size();
|
||||
}
|
||||
|
||||
|
||||
@ -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<class T>
|
||||
Foam::PtrList<T>::PtrList(PtrList<T>& list, bool reuse)
|
||||
:
|
||||
UPtrList<T>(list, reuse)
|
||||
template<bool CheckSelf>
|
||||
void Foam::PtrList<T>::copyPtrList(const UPtrList<T>& 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; i<len; ++i)
|
||||
if (FOAM_UNLIKELY(this == &list))
|
||||
{
|
||||
this->ptrs_[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<T>::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<class T>
|
||||
Foam::PtrList<T>::PtrList(const SLPtrList<T>& list)
|
||||
:
|
||||
@ -122,45 +151,4 @@ void Foam::PtrList<T>::resize(const label newLen)
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
void Foam::PtrList<T>::operator=(const PtrList<T>& 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; i<newLen; ++i)
|
||||
{
|
||||
(*this)[i] = list[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy values for existing entries
|
||||
for (label i=0; i<oldLen; ++i)
|
||||
{
|
||||
(*this)[i] = list[i];
|
||||
}
|
||||
|
||||
// Clone pointers for new entries
|
||||
for (label i=oldLen; i<newLen; ++i)
|
||||
{
|
||||
this->ptrs_[i] = (list[i]).clone().ptr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -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<T>
|
||||
{
|
||||
// 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<bool CheckSelf>
|
||||
void copyPtrList(const UPtrList<T>& list);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
@ -103,7 +112,7 @@ public:
|
||||
inline PtrList(const PtrList<T>& list, const CloneArg& cloneArgs);
|
||||
|
||||
//- Construct as copy or re-use as specified
|
||||
PtrList(PtrList<T>& list, bool reuse);
|
||||
inline PtrList(PtrList<T>& list, bool reuse);
|
||||
|
||||
//- Copy construct using 'clone()' on each element of SLPtrList\<T\>
|
||||
explicit PtrList(const SLPtrList<T>& 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<T>& list);
|
||||
|
||||
//- Copy assignment.
|
||||
// For existing list entries, values are copied from the list.
|
||||
// For new list entries, pointers are cloned from the list.
|
||||
|
||||
@ -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<T>::PtrList(PtrList<T>&& list) noexcept
|
||||
{}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline Foam::PtrList<T>::PtrList(PtrList<T>& list, bool reuse)
|
||||
:
|
||||
UPtrList<T>()
|
||||
{
|
||||
if (reuse)
|
||||
{
|
||||
transfer(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No check for self-assignment
|
||||
copyPtrList<false>(list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline Foam::PtrList<T>::PtrList(UList<T*>& list)
|
||||
:
|
||||
@ -278,7 +295,7 @@ inline Foam::autoPtr<T> Foam::PtrList<T>::release(const label i)
|
||||
template<class T>
|
||||
inline void Foam::PtrList<T>::transfer(PtrList<T>& list)
|
||||
{
|
||||
if (this == &list)
|
||||
if (FOAM_UNLIKELY(this == &list))
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
@ -290,6 +307,22 @@ inline void Foam::PtrList<T>::transfer(PtrList<T>& list)
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
inline void Foam::PtrList<T>::operator=(const UPtrList<T>& list)
|
||||
{
|
||||
// With check for self-assignment
|
||||
this->copyPtrList<true>(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::PtrList<T>::operator=(const PtrList<T>& list)
|
||||
{
|
||||
// With check for self-assignment
|
||||
this->copyPtrList<true>(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::PtrList<T>::operator=(PtrList<T>&& list)
|
||||
{
|
||||
|
||||
@ -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<T>::find_next_not(label pos) const
|
||||
template<class T>
|
||||
void Foam::Detail::PtrListDetail<T>::free()
|
||||
{
|
||||
List<T*>& ptrs = *this;
|
||||
const label len = ptrs.size();
|
||||
|
||||
// Presume they were allocated from front to back...
|
||||
for (label i = len - 1; i >= 0; --i)
|
||||
List<T*>& ptrs = *this;
|
||||
|
||||
for (auto i = this->size()-1; i >= 0; --i)
|
||||
{
|
||||
delete ptrs[i];
|
||||
ptrs[i] = nullptr;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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<class T>
|
||||
Foam::Ostream& Foam::Detail::PtrListDetail<T>::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<class T>
|
||||
Foam::Ostream& Foam::Detail::PtrListDetail<T>::write
|
||||
(
|
||||
|
||||
@ -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<T>::squeezeNull()
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::UPtrList<T>::trimTrailingNull()
|
||||
{
|
||||
label newLen = this->size();
|
||||
|
||||
for (label i = newLen-1; i >= 0 && !ptrs_[i]; --i)
|
||||
{
|
||||
--newLen;
|
||||
}
|
||||
|
||||
// Or mutable?
|
||||
// const_cast<Detail::PtrListDetail<T>&>(ptrs_).setAddressableSize(newLen);
|
||||
|
||||
ptrs_.setAddressableSize(newLen);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::UPtrList<T>::reorder(const labelUList& oldToNew, const bool check)
|
||||
{
|
||||
@ -98,7 +81,7 @@ void Foam::UPtrList<T>::reorder(const labelUList& oldToNew, const bool check)
|
||||
|
||||
Detail::PtrListDetail<T> newList(len);
|
||||
|
||||
for (label i=0; i<len; ++i)
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
const label newIdx = oldToNew[i];
|
||||
|
||||
@ -127,7 +110,8 @@ void Foam::UPtrList<T>::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<T>::sortOrder(const labelUList& order, const bool check)
|
||||
Detail::PtrListDetail<T> newList(len);
|
||||
Detail::PtrListDetail<T> guard(len);
|
||||
|
||||
for (label i=0; i<len; ++i)
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
const label oldIdx = order[i];
|
||||
|
||||
@ -179,16 +163,35 @@ void Foam::UPtrList<T>::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<class T>
|
||||
Foam::Ostream& Foam::UPtrList<T>::printAddresses(Ostream& os) const
|
||||
{
|
||||
return ptrs_.printAddresses(os);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
Foam::Ostream& Foam::UPtrList<T>::writeList
|
||||
(
|
||||
Ostream& os,
|
||||
const bool trimNull
|
||||
) const
|
||||
{
|
||||
return ptrs_.write(os, trimNull);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
Foam::Ostream& Foam::operator<<(Ostream& os, const UPtrList<T>& list)
|
||||
{
|
||||
return list.ptrs_.write(os);
|
||||
return list.writeList(os, false); // Do not ignore null
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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<T>&& 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<< <T>(Ostream& os, const UPtrList<T>& list);
|
||||
|
||||
|
||||
|
||||
@ -269,7 +269,7 @@ public:
|
||||
// Edit
|
||||
|
||||
//- Swap with plain List content. Implies shrink_to_fit().
|
||||
inline void swap(List<T>& list);
|
||||
inline void swap(List<T>& other);
|
||||
|
||||
//- Swap content, independent of sizing parameter
|
||||
template<int AnySizeMin>
|
||||
|
||||
@ -567,12 +567,12 @@ inline void Foam::DynamicField<T, SizeMin>::shrink_to_fit()
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void
|
||||
Foam::DynamicField<T, SizeMin>::swap(List<T>& list)
|
||||
Foam::DynamicField<T, SizeMin>::swap(List<T>& other)
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
== static_cast<const List<T>*>(&other)
|
||||
)
|
||||
{
|
||||
return; // Self-swap is a no-op
|
||||
@ -582,7 +582,7 @@ Foam::DynamicField<T, SizeMin>::swap(List<T>& list)
|
||||
this->shrink_to_fit();
|
||||
|
||||
// Swap storage and addressable size
|
||||
UList<T>::swap(list);
|
||||
UList<T>::swap(other);
|
||||
|
||||
// Update capacity
|
||||
capacity_ = List<T>::size();
|
||||
@ -658,17 +658,22 @@ inline void Foam::DynamicField<T, SizeMin>::transfer
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const UList<T>*>(this)
|
||||
== static_cast<const UList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
|
||||
// Take over storage as-is (without shrink)
|
||||
capacity_ = list.capacity();
|
||||
// Consistent allocated sizing
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
Field<T>::transfer(static_cast<List<T>&>(list));
|
||||
list.clearStorage(); // capacity=0 etc.
|
||||
|
||||
capacity_ = list.capacity();
|
||||
list.setCapacity_unsafe(0); // All contents moved
|
||||
}
|
||||
|
||||
|
||||
@ -681,17 +686,22 @@ inline void Foam::DynamicField<T, SizeMin>::transfer
|
||||
{
|
||||
if
|
||||
(
|
||||
static_cast<const List<T>*>(this)
|
||||
== static_cast<const List<T>*>(&list)
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const UList<T>*>(this)
|
||||
== static_cast<const UList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
return; // Self-assignment is a no-op
|
||||
}
|
||||
|
||||
// Take over storage as-is (without shrink)
|
||||
capacity_ = list.capacity();
|
||||
// Consistent allocated sizing
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
Field<T>::transfer(static_cast<List<T>&>(list));
|
||||
list.clearStorage(); // capacity=0 etc.
|
||||
|
||||
capacity_ = list.capacity();
|
||||
list.setCapacity_unsafe(0); // All contents moved
|
||||
}
|
||||
|
||||
|
||||
@ -744,7 +754,14 @@ inline void Foam::DynamicField<T, SizeMin>::push_back
|
||||
const UList<T>& list
|
||||
)
|
||||
{
|
||||
if (this == &list)
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const UList<T>*>(this)
|
||||
== static_cast<const UList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted push_back to self"
|
||||
@ -764,7 +781,14 @@ inline void Foam::DynamicField<T, SizeMin>::push_back
|
||||
List<T>&& list
|
||||
)
|
||||
{
|
||||
if (this == &list)
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
static_cast<const UList<T>*>(this)
|
||||
== static_cast<const UList<T>*>(&list)
|
||||
)
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted push_back to self"
|
||||
@ -774,6 +798,7 @@ inline void Foam::DynamicField<T, SizeMin>::push_back
|
||||
const label idx = List<T>::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<T, SizeMin>::operator=
|
||||
List<T>&& list
|
||||
)
|
||||
{
|
||||
transfer(list);
|
||||
this->transfer(list);
|
||||
}
|
||||
|
||||
|
||||
@ -890,7 +915,7 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
DynamicField<T, SizeMin>&& list
|
||||
)
|
||||
{
|
||||
transfer(list);
|
||||
this->transfer(list);
|
||||
}
|
||||
|
||||
|
||||
@ -901,7 +926,7 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
DynamicField<T, AnySizeMin>&& list
|
||||
)
|
||||
{
|
||||
transfer(list);
|
||||
this->transfer(list);
|
||||
}
|
||||
|
||||
|
||||
@ -912,7 +937,7 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
DynamicList<T, AnySizeMin>&& list
|
||||
)
|
||||
{
|
||||
transfer(list);
|
||||
this->transfer(list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user