BUG: guard against potential wasted memory in DynamicField
- specialize transfer and swap to ensure allocated capacity isn't forgotten.
This commit is contained in:
parent
4cb763f9d2
commit
35d348c00d
@ -39,10 +39,7 @@ template<class T, int SizeMin>
|
||||
Foam::tmp<Foam::DynamicField<T, SizeMin>>
|
||||
Foam::DynamicField<T, SizeMin>::clone() const
|
||||
{
|
||||
return tmp<DynamicField<T, SizeMin>>
|
||||
(
|
||||
new DynamicField<T, SizeMin>(*this)
|
||||
);
|
||||
return tmp<DynamicField<T, SizeMin>>::New(*this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -51,20 +51,20 @@ template<class T, int SizeMin> class DynamicField;
|
||||
template<class T, int SizeMin>
|
||||
Ostream& operator<<
|
||||
(
|
||||
Ostream&,
|
||||
const DynamicField<T, SizeMin>&
|
||||
Ostream& os,
|
||||
const DynamicField<T, SizeMin>& fld
|
||||
);
|
||||
|
||||
template<class T, int SizeMin>
|
||||
Istream& operator>>
|
||||
(
|
||||
Istream&,
|
||||
DynamicField<T, SizeMin>&
|
||||
Istream& is,
|
||||
DynamicField<T, SizeMin>& fld
|
||||
);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class DynamicField Declaration
|
||||
Class DynamicField Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class T, int SizeMin=64>
|
||||
@ -84,7 +84,7 @@ class DynamicField
|
||||
|
||||
//- Copy assignment from another list
|
||||
template<class ListType>
|
||||
inline void assignDynField(const ListType& lst);
|
||||
inline void assignDynField(const ListType& list);
|
||||
|
||||
public:
|
||||
|
||||
@ -102,15 +102,25 @@ public:
|
||||
//- Construct null
|
||||
inline constexpr DynamicField() noexcept;
|
||||
|
||||
//- Construct with given capacity.
|
||||
//- Construct empty field with given reserve size.
|
||||
explicit inline DynamicField(const label len);
|
||||
|
||||
//- Construct given size and initial value
|
||||
inline DynamicField(const label len, const T& val);
|
||||
|
||||
//- Construct given size and initial value of zero
|
||||
inline DynamicField(const label len, const zero);
|
||||
|
||||
//- Copy construct
|
||||
inline DynamicField(const DynamicField<T, SizeMin>& lst);
|
||||
inline DynamicField(const DynamicField<T, SizeMin>& list);
|
||||
|
||||
//- Copy construct with different sizing parameters
|
||||
template<int AnySizeMin>
|
||||
inline DynamicField(const DynamicField<T, AnySizeMin>& list);
|
||||
|
||||
//- Copy construct from UList. Size set to UList size.
|
||||
// Also constructs from DynamicField with different sizing parameters.
|
||||
explicit inline DynamicField(const UList<T>& lst);
|
||||
explicit inline DynamicField(const UList<T>& list);
|
||||
|
||||
//- Copy construct from UIndirectList
|
||||
explicit inline DynamicField(const UIndirectList<T>& list);
|
||||
@ -118,9 +128,13 @@ public:
|
||||
//- Move construct from List contents
|
||||
explicit inline DynamicField(List<T>&& content);
|
||||
|
||||
//- Move construct from Field contents
|
||||
//- Move construct from dynamic Field contents
|
||||
inline DynamicField(DynamicField<T, SizeMin>&& content);
|
||||
|
||||
//- Move construct with different sizing parameters
|
||||
template<int AnySizeMin>
|
||||
inline DynamicField(DynamicField<T, AnySizeMin>&& content);
|
||||
|
||||
//- Construct by 1 to 1 mapping from the given field
|
||||
inline DynamicField
|
||||
(
|
||||
@ -152,87 +166,108 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
// Access
|
||||
|
||||
//- Size of the underlying storage.
|
||||
inline label capacity() const;
|
||||
//- Size of the underlying storage.
|
||||
inline label capacity() const;
|
||||
|
||||
// Edit
|
||||
// Edit
|
||||
|
||||
//- Alter the size of the underlying storage.
|
||||
// The addressed size will be truncated if needed to fit, but will
|
||||
// remain otherwise untouched.
|
||||
// Use this or reserve() in combination with append().
|
||||
inline void setCapacity(const label nElem);
|
||||
//- Alter the size of the underlying storage.
|
||||
// The addressed size will be truncated if needed to fit, but will
|
||||
// remain otherwise untouched.
|
||||
// Use this or reserve() in combination with append().
|
||||
inline void setCapacity(const label nElem);
|
||||
|
||||
//- Alter the addressed list size.
|
||||
// New space will be allocated if required.
|
||||
// Use this to resize the list prior to using the operator[] for
|
||||
// setting values (as per List usage).
|
||||
inline void setSize(const label nElem);
|
||||
//- Alter the addressed list size.
|
||||
// New space will be allocated if required.
|
||||
// Use this to resize the list prior to using the operator[] for
|
||||
// setting values (as per List usage).
|
||||
inline void setSize(const label nElem);
|
||||
|
||||
//- Alter the addressed list size and fill new space with a
|
||||
// constant.
|
||||
inline void setSize(const label nElem, const T& val);
|
||||
//- Alter the addressed list size and fill new space with a constant.
|
||||
inline void setSize(const label nElem, const T& val);
|
||||
|
||||
//- Alter the addressed list size.
|
||||
// New space will be allocated if required.
|
||||
// Use this to resize the list prior to using the operator[] for
|
||||
// setting values (as per List usage).
|
||||
inline void resize(const label nElem);
|
||||
//- Alter the addressed list size.
|
||||
// New space will be allocated if required.
|
||||
// Use this to resize the list prior to using the operator[] for
|
||||
// setting values (as per List usage).
|
||||
inline void resize(const label nElem);
|
||||
|
||||
//- Alter the addressed list size and fill new space with a
|
||||
// constant.
|
||||
inline void resize(const label nElem, const T& val);
|
||||
//- Alter the addressed list size and fill new space with a
|
||||
// constant.
|
||||
inline void resize(const label nElem, const T& val);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
inline void reserve(const label nElem);
|
||||
//- Reserve allocation space for at least this size.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
inline void reserve(const label nElem);
|
||||
|
||||
//- Clear the addressed list, i.e. set the size to zero.
|
||||
// Allocated size does not change
|
||||
inline void clear();
|
||||
//- Clear the addressed list, i.e. set the size to zero.
|
||||
// Allocated size does not change
|
||||
inline void clear();
|
||||
|
||||
//- Clear the list and delete storage.
|
||||
inline void clearStorage();
|
||||
//- Clear the list and delete storage.
|
||||
inline void clearStorage();
|
||||
|
||||
//- Expand the addressable size to fit the allocated capacity.
|
||||
// Returns the previous addressable size.
|
||||
inline label expandStorage();
|
||||
//- Expand the addressable size to fit the allocated capacity.
|
||||
// Returns the previous addressable size.
|
||||
inline label expandStorage();
|
||||
|
||||
//- Shrink the allocated space to the number of elements used.
|
||||
// Returns a reference to the DynamicField.
|
||||
inline DynamicField<T, SizeMin>& shrink();
|
||||
//- Shrink the allocated space to the number of elements used.
|
||||
// Returns a reference to the DynamicField.
|
||||
inline DynamicField<T, SizeMin>& shrink();
|
||||
|
||||
//- Swap content with any sized DynamicField
|
||||
template<int AnySizeMin>
|
||||
inline void swap(DynamicField<T, AnySizeMin>& list);
|
||||
|
||||
//- Transfer the parameter contents into this
|
||||
inline void transfer(List<T>& list);
|
||||
|
||||
//- Transfer the parameter contents into this
|
||||
template<int AnySizeMin>
|
||||
inline void transfer(DynamicList<T, AnySizeMin>& list);
|
||||
|
||||
//- Transfer the parameter contents into this
|
||||
template<int AnySizeMin>
|
||||
inline void transfer(DynamicField<T, AnySizeMin>& list);
|
||||
|
||||
|
||||
// Member Operators
|
||||
//- Append an element at the end of the list
|
||||
inline DynamicField<T, SizeMin>&
|
||||
append(const T& val);
|
||||
|
||||
//- Append an element at the end of the list
|
||||
inline DynamicField<T, SizeMin>&
|
||||
append(const T& val);
|
||||
//- Append a List at the end of this list
|
||||
inline DynamicField<T, SizeMin>&
|
||||
append(const UList<T>& list);
|
||||
|
||||
//- Append a List at the end of this list
|
||||
inline DynamicField<T, SizeMin>&
|
||||
append(const UList<T>& lst);
|
||||
//- Remove and return the top element
|
||||
inline T remove();
|
||||
|
||||
//- Remove and return the top element
|
||||
inline T remove();
|
||||
|
||||
//- Return non-const access to an element, resizing list if
|
||||
// necessary
|
||||
inline T& operator()(const label i);
|
||||
// Member Operators
|
||||
|
||||
//- Assignment of all addressed entries to the given value
|
||||
inline void operator=(const T& val);
|
||||
//- Return non-const access to an element, resizing list if necessary
|
||||
inline T& operator()(const label i);
|
||||
|
||||
//- Assignment to DynamicField
|
||||
inline void operator=
|
||||
(
|
||||
const DynamicField<T, SizeMin>& lst
|
||||
);
|
||||
//- Assign addressed entries to the given value
|
||||
inline void operator=(const T& val);
|
||||
|
||||
//- Assignment to UList
|
||||
inline void operator=(const UList<T>& lst);
|
||||
//- Copy assignment
|
||||
inline void operator=(const UList<T>& list);
|
||||
|
||||
//- Copy assignment
|
||||
inline void operator=(const DynamicField<T, SizeMin>& list);
|
||||
|
||||
//- Move assignment
|
||||
inline void operator=(List<T>&& list);
|
||||
|
||||
//- Move assignment
|
||||
inline void operator=(DynamicField<T, SizeMin>&& list);
|
||||
|
||||
//- Move assignment
|
||||
template<int AnySizeMin>
|
||||
inline void operator=(DynamicField<T, AnySizeMin>&& list);
|
||||
|
||||
};
|
||||
|
||||
|
@ -29,23 +29,23 @@ template<class T, int SizeMin>
|
||||
template<class ListType>
|
||||
inline void Foam::DynamicField<T, SizeMin>::assignDynField
|
||||
(
|
||||
const ListType& lst
|
||||
const ListType& list
|
||||
)
|
||||
{
|
||||
const label newSize = lst.size();
|
||||
const label newSize = list.size();
|
||||
|
||||
if (capacity_ >= newSize)
|
||||
{
|
||||
// Can copy w/o reallocating - adjust addressable size accordingly.
|
||||
Field<T>::size(lst.size());
|
||||
Field<T>::operator=(lst);
|
||||
Field<T>::size(list.size());
|
||||
Field<T>::operator=(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure list size consistency prior to copying.
|
||||
Field<T>::size(capacity_);
|
||||
|
||||
Field<T>::operator=(lst);
|
||||
Field<T>::operator=(list);
|
||||
capacity_ = Field<T>::size();
|
||||
}
|
||||
}
|
||||
@ -62,15 +62,11 @@ inline constexpr Foam::DynamicField<T, SizeMin>::DynamicField() noexcept
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
const label len
|
||||
)
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField(const label len)
|
||||
:
|
||||
Field<T>(len),
|
||||
capacity_(Field<T>::size())
|
||||
{
|
||||
// We could also enforce sizing granularity
|
||||
Field<T>::size(0);
|
||||
}
|
||||
|
||||
@ -78,21 +74,11 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
const DynamicField<T, SizeMin>& lst
|
||||
const label len,
|
||||
const T& val
|
||||
)
|
||||
:
|
||||
Field<T>(lst),
|
||||
capacity_(lst.capacity())
|
||||
{}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
const UList<T>& lst
|
||||
)
|
||||
:
|
||||
Field<T>(lst),
|
||||
Field<T>(len, val),
|
||||
capacity_(Field<T>::size())
|
||||
{}
|
||||
|
||||
@ -100,10 +86,56 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
const UIndirectList<T>& lst
|
||||
const label len,
|
||||
const zero
|
||||
)
|
||||
:
|
||||
Field<T>(lst),
|
||||
Field<T>(len, Zero),
|
||||
capacity_(Field<T>::size())
|
||||
{}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
const DynamicField<T, SizeMin>& list
|
||||
)
|
||||
:
|
||||
Field<T>(list),
|
||||
capacity_(Field<T>::size())
|
||||
{}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
const DynamicField<T, AnySizeMin>& list
|
||||
)
|
||||
:
|
||||
Field<T>(list),
|
||||
capacity_(Field<T>::size())
|
||||
{}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
const UList<T>& list
|
||||
)
|
||||
:
|
||||
Field<T>(list),
|
||||
capacity_(Field<T>::size())
|
||||
{}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
const UIndirectList<T>& list
|
||||
)
|
||||
:
|
||||
Field<T>(list),
|
||||
capacity_(Field<T>::size())
|
||||
{}
|
||||
|
||||
@ -125,10 +157,24 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
DynamicField<T, SizeMin>&& content
|
||||
)
|
||||
:
|
||||
Field<T>(std::move(content)),
|
||||
capacity_(Field<T>::size())
|
||||
Field<T>(),
|
||||
capacity_(0)
|
||||
{
|
||||
content.clear();
|
||||
transfer(content);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
DynamicField<T, AnySizeMin>&& content
|
||||
)
|
||||
:
|
||||
Field<T>(),
|
||||
capacity_(0)
|
||||
{
|
||||
transfer(content);
|
||||
}
|
||||
|
||||
|
||||
@ -173,8 +219,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::label Foam::DynamicField<T, SizeMin>::capacity()
|
||||
const
|
||||
inline Foam::label Foam::DynamicField<T, SizeMin>::capacity() const
|
||||
{
|
||||
return capacity_;
|
||||
}
|
||||
@ -343,6 +388,73 @@ Foam::DynamicField<T, SizeMin>::shrink()
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::swap
|
||||
(
|
||||
DynamicField<T, AnySizeMin>& lst
|
||||
)
|
||||
{
|
||||
DynamicList<T, SizeMin>& cur = *this;
|
||||
|
||||
// Make addressable size identical to the allocated capacity
|
||||
const label oldSize1 = cur.expandStorage();
|
||||
const label oldSize2 = lst.expandStorage();
|
||||
|
||||
// Swap storage
|
||||
Field<T>::swap(lst);
|
||||
|
||||
// Match capacity to the underlying allocated list size
|
||||
cur.setCapacity(cur.size());
|
||||
lst.setCapacity(lst.size());
|
||||
|
||||
// Set addressable size
|
||||
cur.setSize(oldSize2);
|
||||
lst.setSize(oldSize1);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::transfer(List<T>& list)
|
||||
{
|
||||
// Take over storage, clear addressing for list.
|
||||
capacity_ = list.size();
|
||||
Field<T>::transfer(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::transfer
|
||||
(
|
||||
DynamicList<T, AnySizeMin>& list
|
||||
)
|
||||
{
|
||||
// Take over storage as-is (without shrink, without using SizeMin)
|
||||
// clear addressing and storage for old list.
|
||||
capacity_ = list.capacity();
|
||||
|
||||
Field<T>::transfer(static_cast<Field<T>&>(list));
|
||||
list.clearStorage(); // Ensure capacity=0
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::transfer
|
||||
(
|
||||
DynamicField<T, AnySizeMin>& list
|
||||
)
|
||||
{
|
||||
// Take over storage as-is (without shrink, without using SizeMin)
|
||||
// clear addressing and storage for old list.
|
||||
capacity_ = list.capacity();
|
||||
|
||||
Field<T>::transfer(static_cast<Field<T>&>(list));
|
||||
list.clearStorage(); // Ensure capacity=0
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>&
|
||||
Foam::DynamicField<T, SizeMin>::append
|
||||
@ -353,7 +465,7 @@ Foam::DynamicField<T, SizeMin>::append
|
||||
const label idx = List<T>::size();
|
||||
setSize(idx + 1);
|
||||
|
||||
this->operator[](idx) = val;
|
||||
this->operator[](idx) = val; // copy element
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -362,21 +474,21 @@ template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>&
|
||||
Foam::DynamicField<T, SizeMin>::append
|
||||
(
|
||||
const UList<T>& lst
|
||||
const UList<T>& list
|
||||
)
|
||||
{
|
||||
if (this == &lst)
|
||||
if (this == &list)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "attempted appending to self" << abort(FatalError);
|
||||
}
|
||||
|
||||
label nextFree = List<T>::size();
|
||||
setSize(nextFree + lst.size());
|
||||
label idx = List<T>::size();
|
||||
setSize(idx + list.size());
|
||||
|
||||
forAll(lst, i)
|
||||
for (const T& val : list)
|
||||
{
|
||||
this->operator[](nextFree++) = lst[i];
|
||||
this->operator[](idx++) = val; // copy element
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -432,26 +544,57 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
(
|
||||
const DynamicField<T, SizeMin>& lst
|
||||
const UList<T>& list
|
||||
)
|
||||
{
|
||||
if (this == &lst)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted assignment to self" << abort(FatalError);
|
||||
}
|
||||
|
||||
assignDynField(lst);
|
||||
assignDynField(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
(
|
||||
const UList<T>& lst
|
||||
const DynamicField<T, SizeMin>& list
|
||||
)
|
||||
{
|
||||
assignDynField(lst);
|
||||
if (this == &list)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted assignment to self" << abort(FatalError);
|
||||
}
|
||||
|
||||
assignDynField(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
(
|
||||
List<T>&& list
|
||||
)
|
||||
{
|
||||
transfer(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
(
|
||||
DynamicField<T, SizeMin>&& list
|
||||
)
|
||||
{
|
||||
transfer(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
(
|
||||
DynamicField<T, AnySizeMin>&& list
|
||||
)
|
||||
{
|
||||
transfer(list);
|
||||
}
|
||||
|
||||
|
||||
|
@ -186,5 +186,4 @@ inline void Foam::Field<Type>::operator=(const zero)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
Loading…
Reference in New Issue
Block a user