From 58f46a6b571c9bad01a6c9addf228a1cfc16a05d Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Tue, 24 Oct 2017 10:29:09 +0200 Subject: [PATCH] BUG: failed swap/transfer for DynamicList with different sizing parameters - now use public functions instead of direct access of private 'capacity_' information --- .../test/DynamicList/Test-DynamicList.C | 29 +++++++++ .../Lists/DynamicList/DynamicList.H | 8 +++ .../Lists/DynamicList/DynamicListI.H | 59 ++++++++++++++++--- .../fields/Fields/DynamicField/DynamicField.H | 34 +++++------ 4 files changed, 106 insertions(+), 24 deletions(-) diff --git a/applications/test/DynamicList/Test-DynamicList.C b/applications/test/DynamicList/Test-DynamicList.C index ca3f4fc787..11111aad00 100644 --- a/applications/test/DynamicList/Test-DynamicList.C +++ b/applications/test/DynamicList/Test-DynamicList.C @@ -46,6 +46,14 @@ void printInfo if (showSize) { Info<< " size=\"" << lst.size() << "\""; + if (lst.cdata()) + { + Info<< " ptr=\"" << long(lst.cdata()) << "\""; + } + else + { + Info<< " ptr=\"nullptr\""; + } } Info<< ">" << nl << flatOutput(lst) << nl << "</" << tag << ">" << endl; } @@ -64,6 +72,14 @@ void printInfo { Info<< " size=\"" << lst.size() << "\" capacity=\"" << lst.capacity() << "\""; + if (lst.cdata()) + { + Info<< " ptr=\"" << long(lst.cdata()) << "\""; + } + else + { + Info<< " ptr=\"nullptr\""; + } } Info<< ">" << nl << flatOutput(lst) << nl << "</" << tag << ">" << endl; } @@ -284,6 +300,19 @@ int main(int argc, char *argv[]) << flatOutput(input1) << " / " << flatOutput(input2) << nl; + Info<< "test move dissimilar sizing:" << nl; + list1 = list2; + list1.reserve(100); + + // DynamicList<label,1000> list3; // (std::move(list1)); + DynamicList<label,1000> list3(std::move(list1)); + Info<< "orig: " << flatOutput(list1) << nl; + + // list3.swap(list1); + // list3 = std::move(list1); + + printInfo("input", list1, true); + printInfo("output", list3, true); input1 = list2; diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H index 4dae845ed3..a5fe88bd50 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H @@ -158,6 +158,10 @@ public: //- Move construct. inline DynamicList(DynamicList<T, SizeMin>&& lst); + //- Move construct with different sizing parameters + template<int AnySizeMin> + inline DynamicList(DynamicList<T, AnySizeMin>&& lst); + //- Move construct from List inline DynamicList(List<T>&& lst); @@ -212,6 +216,10 @@ public: //- 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(); + //- Shrink the allocated space to the number of elements used. // Returns a reference to the DynamicList. inline DynamicList<T, SizeMin>& shrink(); diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H index a41f284f63..2fcfc66062 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H @@ -206,6 +206,19 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList } +template<class T, int SizeMin> +template<int AnySizeMin> +inline Foam::DynamicList<T, SizeMin>::DynamicList +( + DynamicList<T, AnySizeMin>&& lst +) +: + capacity_(0) +{ + transfer(lst); +} + + template<class T, int SizeMin> inline Foam::DynamicList<T, SizeMin>::DynamicList ( @@ -360,6 +373,18 @@ inline void Foam::DynamicList<T, SizeMin>::clearStorage() } +template<class T, int SizeMin> +inline Foam::label Foam::DynamicList<T, SizeMin>::expandStorage() +{ + const label nextFree = List<T>::size(); + + // Allow addressing into the entire list + List<T>::size(capacity_); + + return nextFree; +} + + template<class T, int SizeMin> inline Foam::DynamicList<T, SizeMin>& Foam::DynamicList<T, SizeMin>::shrink() @@ -386,8 +411,26 @@ inline void Foam::DynamicList<T, SizeMin>::swap DynamicList<T, AnySizeMin>& lst ) { - Foam::Swap(static_cast<UList<T>&>(*this), static_cast<UList<T>&>(lst)); - Foam::Swap(capacity_, lst.capacity_); + 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 + Foam::Swap + ( + static_cast<UList<T>&>(cur), + static_cast<UList<T>&>(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); } @@ -409,10 +452,12 @@ Foam::DynamicList<T, SizeMin>::transfer DynamicList<T, AnySizeMin>& lst ) { - // Take over storage as-is (without shrink), clear addressing for lst. - capacity_ = lst.capacity_; - lst.capacity_ = 0; + // Take over storage as-is (without shrink, without using SizeMin) + // clear addressing and storage for old lst. + capacity_ = lst.capacity(); + List<T>::transfer(static_cast<List<T>&>(lst)); + lst.clearStorage(); // Ensure capacity=0 } @@ -565,7 +610,7 @@ Foam::DynamicList<T, SizeMin>::append ) { append(std::move(static_cast<List<T>&>(lst))); - lst.clearStorage(); // Ensure capacity=0 too + lst.clearStorage(); // Ensure capacity=0 return *this; } @@ -579,7 +624,7 @@ Foam::DynamicList<T, SizeMin>::append ) { append(std::move(static_cast<List<T>&>(lst))); - lst.clearStorage(); // Ensure capacity=0 too + lst.clearStorage(); // Ensure capacity=0 return *this; } diff --git a/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H b/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H index fd5b3a5486..ea2f2a7e5b 100644 --- a/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H +++ b/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H @@ -103,17 +103,17 @@ public: inline DynamicField(); //- Construct given size. - explicit inline DynamicField(const label); + explicit inline DynamicField(const label nElem); //- Construct from UList. Size set to UList size. // Also constructs from DynamicField with different sizing parameters. - explicit inline DynamicField(const UList<T>&); + explicit inline DynamicField(const UList<T>& lst); //- Construct by transferring the parameter contents - explicit inline DynamicField(const Xfer<List<T>>&); + explicit inline DynamicField(const Xfer<List<T>>& lst); //- Construct by transferring the parameter contents - explicit inline DynamicField(const Xfer<Field<T>>&); + explicit inline DynamicField(const Xfer<Field<T>>& lst); //- Construct by 1 to 1 mapping from the given field inline DynamicField @@ -138,16 +138,16 @@ public: ); //- Construct copy - inline DynamicField(const DynamicField<T, SizeMin>&); + inline DynamicField(const DynamicField<T, SizeMin>& lst); //- Construct by transferring the Field contents inline DynamicField ( - const Xfer<DynamicField<T, SizeMin>>& + const Xfer<DynamicField<T, SizeMin>>& lst ); //- Construct from Istream. Size set to size of list read. - explicit DynamicField(Istream&); + explicit DynamicField(Istream& is); //- Clone tmp<DynamicField<T, SizeMin>> clone() const; @@ -166,31 +166,31 @@ public: // 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); + 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); + inline void setSize(const label nElem); //- Alter the addressed list size and fill new space with a // constant. - inline void setSize(const label, const T&); + 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); + inline void resize(const label nElem); //- Alter the addressed list size and fill new space with a // constant. - inline void resize(const label, const T& val); + 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); + inline void reserve(const label nElem); //- Clear the addressed list, i.e. set the size to zero. // Allocated size does not change @@ -222,19 +222,19 @@ public: //- Return non-const access to an element, resizing list if // necessary - inline T& operator()(const label); + inline T& operator()(const label elemI); //- Assignment of all addressed entries to the given value - inline void operator=(const T&); + inline void operator=(const T& val); //- Assignment to DynamicField inline void operator= ( - const DynamicField<T, SizeMin>& + const DynamicField<T, SizeMin>& lst ); //- Assignment to UList - inline void operator=(const UList<T>&); + inline void operator=(const UList<T>& lst); }; -- GitLab