FIX: incorrect DynamicList resizing logic (memory pool)

- reserve() did not set the addressable size to the current capacity
  before resizing, which meant that the delete[] would not have the
  true allocated size. Only affects memory-pool usage (#3381), which
  is not yet integrated

ENH: remove unused DynamicList '*_unsafe()' methods

- can result in a mismatch between allocated and addressed sizes,
  which becomes important for memory-pool usage.
This commit is contained in:
Mark Olesen
2025-06-23 09:11:18 +02:00
committed by Mark Olesen
parent 6ac50a3307
commit a68ed1371f
9 changed files with 79 additions and 119 deletions

View File

@ -106,7 +106,7 @@ void printMyString(const UList<string>& lst)
{
MyStrings slist2(lst);
Info<<slist2 << nl;
Info<< slist2 << nl;
}
@ -204,16 +204,6 @@ int main(int argc, char *argv[])
Info<<" " << *iter;
}
Info<< nl;
Info<< "data:" << Foam::name(ident.cdata())
<< " size:" << ident.size() << nl;
Info<< "resize_unsafe(10)" << nl;
ident.resize_unsafe(10);
Info<< "data:" << Foam::name(ident.cdata())
<< " size:" << ident.size() << nl;
}
if (false)
@ -370,7 +360,7 @@ int main(int argc, char *argv[])
auto shrtList = ListOps::create<short>
(
longLabelList,
[](const label& val){ return val; }
[](label val){ return val; }
);
printListOutputType<short>("short") << nl;
@ -567,7 +557,7 @@ int main(int argc, char *argv[])
auto scalars = ListOps::create<scalar>
(
labels,
[](const label& val){ return scalar(1.5*val); }
[](label val){ return scalar(1.5*val); }
);
Info<< "scalars: " << flatOutput(scalars) << endl;
}
@ -576,7 +566,7 @@ int main(int argc, char *argv[])
auto vectors = ListOps::create<vector>
(
labels,
[](const label& val){ return vector(1.2*val, -1.2*val, 0); }
[](label val){ return vector(1.2*val, -1.2*val, 0); }
);
Info<< "vectors: " << flatOutput(vectors) << endl;
}
@ -585,7 +575,7 @@ int main(int argc, char *argv[])
auto longs = ListOps::create<long>
(
labels,
[](const label& val){ return val; }
[](label val){ return val; }
);
Info<< "longs: " << flatOutput(longs) << endl;
}
@ -603,7 +593,7 @@ int main(int argc, char *argv[])
(
labelRange().cbegin(),
labelRange(15).cend(),
[](const label& val){ return scalar(-1.125*val); }
[](label val){ return scalar(-1.125*val); }
);
Info<< "scalars: " << flatOutput(scalars) << endl;
}

View File

@ -203,7 +203,7 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size, allocating new
//- space if required and \em retaining old content.
@ -251,11 +251,6 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
// Edit

View File

@ -68,7 +68,9 @@ inline void Foam::DynamicList<T, SizeMin>::doCapacity
// Addressable length, possibly truncated by new capacity
const label currLen = Foam::min(List<T>::size(), newCapacity);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
if (nocopy)
{
List<T>::resize_nocopy(newCapacity);
@ -95,6 +97,9 @@ inline void Foam::DynamicList<T, SizeMin>::doReserve
// Preserve addressed size
const label currLen = List<T>::size();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
@ -105,8 +110,10 @@ inline void Foam::DynamicList<T, SizeMin>::doReserve
}
else
{
List<T>::resize(capacity_);
List<T>::resize_copy(currLen, capacity_);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -271,7 +278,7 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList
List<T>(std::move(static_cast<List<T>&>(list))),
capacity_(list.capacity())
{
list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.setCapacity_unsafe(0); // All contents moved
}
@ -285,7 +292,7 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList
List<T>(std::move(static_cast<List<T>&>(list))),
capacity_(list.capacity())
{
list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.setCapacity_unsafe(0); // All contents moved
}
@ -361,8 +368,15 @@ inline void Foam::DynamicList<T, SizeMin>::reserve_exact
// Preserve addressed size
const label currLen = List<T>::size();
capacity_ = len;
List<T>::resize(capacity_);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// if (!nocopy)
{
List<T>::resize_copy(currLen, len);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -449,18 +463,6 @@ inline void Foam::DynamicList<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::shrink_unsafe()
{
if (List<T>::empty())
{
// Delete storage if empty
List<T>::clear();
}
capacity_ = List<T>::size();
}
template<class T, int SizeMin>
inline void
Foam::DynamicList<T, SizeMin>::swap(List<T>& list)

View File

@ -236,13 +236,6 @@ public:
// Otherwise the contents will be uninitialized.
inline void resize_nocopy(const label len);
//- Change the addressed list size directly without affecting
//- any memory management (advanced usage).
//
// It is left to the caller to avoid \em unsafe lengthening beyond
// the allocated memory region.
inline void resize_unsafe(const label len) noexcept;
//- Alias for resize()
void setSize(const label n) { this->resize(n); }

View File

@ -178,13 +178,6 @@ inline void Foam::List<T>::resize_nocopy(const label len)
}
template<class T>
inline void Foam::List<T>::resize_unsafe(const label len) noexcept
{
UList<T>::setAddressableSize(len);
}
template<class T>
inline T& Foam::List<T>::newElmt(const label i)
{

View File

@ -112,23 +112,26 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size.
// New entries are initialized to nullptr.
inline void reserve(const label len);
//- Reserve allocation space for at least this size.
//- If allocation is required, uses the specified size
//- without any other resizing logic.
// New entries are initialized to nullptr.
inline void reserve_exact(const label len);
//- Alter the addressed list size.
inline void resize(const label newLen);
// New entries are initialized to nullptr.
inline void resize(const label len);
//- Set the addressed list to the given size,
//- deleting all existing entries.
//- Afterwards the list contains all \c nullptr entries.
inline void resize_null(const label newLen);
inline void resize_null(const label len);
//- Clear the addressed list, i.e. set the size to zero.
// Allocated size does not change
@ -140,11 +143,6 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
//- Alias for shrink_to_fit()
void shrink() { this->shrink_to_fit(); }

View File

@ -82,10 +82,7 @@ inline Foam::PtrDynList<T, SizeMin>::PtrDynList
PtrList<T>(std::move(list)),
capacity_(list.capacity())
{
// FUTURE:
// list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.clearStorage(); // capacity=0 etc.
list.setCapacity_unsafe(0); // All contents moved
}
@ -99,10 +96,7 @@ inline Foam::PtrDynList<T, SizeMin>::PtrDynList
PtrList<T>(std::move(list)),
capacity_(list.capacity())
{
// FUTURE:
// list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.clearStorage(); // capacity=0 etc.
list.setCapacity_unsafe(0); // All contents moved
}
@ -135,11 +129,17 @@ inline void Foam::PtrDynList<T, SizeMin>::reserve(const label len)
// Preserve addressed size
const label currLen = PtrList<T>::size();
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
// No PtrList<T>::resize_copy(...) -> copying nullptr is cheap
PtrList<T>::resize(capacity_);
capacity_ = PtrList<T>::size();
PtrList<T>::setAddressableSize(currLen);
}
}
@ -153,8 +153,13 @@ inline void Foam::PtrDynList<T, SizeMin>::reserve_exact(const label len)
// Preserve addressed size
const label currLen = PtrList<T>::size();
capacity_ = len;
PtrList<T>::resize(capacity_);
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// No PtrList<T>::resize_copy(...) -> copying nullptr is cheap
PtrList<T>::resize(len);
capacity_ = PtrList<T>::size();
PtrList<T>::setAddressableSize(currLen);
}
}
@ -164,16 +169,12 @@ template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::resize(const label newLen)
{
auto& ptrs = this->ptrs_;
const label oldLen = ptrs.size();
if (capacity_ < newLen)
{
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(newLen, capacity_);
PtrList<T>::resize(capacity_);
// Extend list
this->reserve(newLen);
}
else if (newLen != oldLen)
{
@ -191,13 +192,16 @@ inline void Foam::PtrDynList<T, SizeMin>::resize(const label newLen)
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label newLen)
inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label len)
{
if (capacity_ < newLen)
if (capacity_ < len)
{
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(newLen, capacity_);
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
PtrList<T>::resize_null(capacity_);
}
@ -207,7 +211,7 @@ inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label newLen)
}
// Adjust addressed size
PtrList<T>::setAddressableSize(newLen);
PtrList<T>::setAddressableSize(len);
}
@ -240,18 +244,6 @@ inline void Foam::PtrDynList<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::shrink_unsafe()
{
if (PtrList<T>::empty())
{
// Delete empty list
PtrList<T>::clear();
}
capacity_ = PtrList<T>::size();
}
template<class T, int SizeMin>
inline Foam::label Foam::PtrDynList<T, SizeMin>::squeezeNull()
{

View File

@ -217,7 +217,7 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size, allocating new
//- space if required and \em retaining old content.
@ -265,11 +265,6 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
// Edit

View File

@ -66,7 +66,9 @@ inline void Foam::DynamicField<T, SizeMin>::doCapacity
// Addressable length, possibly truncated by new capacity
const label currLen = Foam::min(List<T>::size(), newCapacity);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
if (nocopy)
{
List<T>::resize_nocopy(newCapacity);
@ -93,6 +95,9 @@ inline void Foam::DynamicField<T, SizeMin>::doReserve
// Preserve addressed size
const label currLen = List<T>::size();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
@ -103,8 +108,10 @@ inline void Foam::DynamicField<T, SizeMin>::doReserve
}
else
{
List<T>::resize(capacity_);
List<T>::resize_copy(currLen, capacity_);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -246,7 +253,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
content.setCapacity_unsafe(0); // All contents moved
}
@ -259,7 +266,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
content.setCapacity_unsafe(0); // All contents moved
}
@ -273,7 +280,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
content.setCapacity_unsafe(0); // All contents moved
}
@ -292,7 +299,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
{
Field<T>::transfer(static_cast<List<T>&>(content));
capacity_ = content.capacity();
content.setCapacity_unsafe(0);
content.setCapacity_unsafe(0); // All contents moved
}
else
{
@ -317,7 +324,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
{
Field<T>::transfer(static_cast<List<T>&>(content));
capacity_ = content.capacity();
content.setCapacity_unsafe(0);
content.setCapacity_unsafe(0); // All contents moved
}
else
{
@ -462,8 +469,15 @@ inline void Foam::DynamicField<T, SizeMin>::reserve_exact
// Preserve addressed size
const label currLen = List<T>::size();
capacity_ = len;
List<T>::resize(capacity_);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// if (!nocopy)
{
List<T>::resize_copy(currLen, len);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -551,18 +565,6 @@ inline void Foam::DynamicField<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::DynamicField<T, SizeMin>::shrink_unsafe()
{
if (List<T>::empty())
{
// Delete storage if empty
List<T>::clear();
}
capacity_ = List<T>::size();
}
template<class T, int SizeMin>
inline void
Foam::DynamicField<T, SizeMin>::swap(List<T>& list)