diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H index c074820f4c..46fae4d5e7 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H @@ -250,7 +250,7 @@ public: //- Swap content, independent of sizing parameter template - inline void swap(DynamicList& other); + inline void swap(DynamicList& other) noexcept; //- Transfer contents of the argument List into this. inline void transfer(List& list); diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H index 27d3209987..ccf07d15a5 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H @@ -373,6 +373,18 @@ inline void Foam::DynamicList::resize_nocopy } +// template +// inline void Foam::DynamicList::resize_fill +// ( +// const label len, +// const T& val +// ) +// { +// this->doResize(true, len); // nocopy = true +// this->fill_uniform(val); +// } + + template inline void Foam::DynamicList::resize ( @@ -448,7 +460,7 @@ template inline void Foam::DynamicList::swap ( DynamicList& other -) +) noexcept { if ( diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListIO.C b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListIO.C index 5fa5e9d00f..37b7ae822d 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListIO.C +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListIO.C @@ -43,13 +43,10 @@ Foam::DynamicList::DynamicList(Istream& is) } -// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // template -Foam::Istream& Foam::DynamicList::readList -( - Istream& is -) +Foam::Istream& Foam::DynamicList::readList(Istream& is) { DynamicList& list = *this; diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H b/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H index 25874664b5..68144b2df5 100644 --- a/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H +++ b/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H @@ -28,6 +28,7 @@ License #include "UList.H" #include "SLList.H" +// already included by stdFoam.H // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // @@ -372,6 +373,7 @@ inline void Foam::FixedList::resize_nocopy(const label n) template inline void Foam::FixedList::fill(const T& val) { + // Usually small enough that parallel execution is pointless... for (unsigned i=0; i::fill(const T& val) template inline void Foam::FixedList::fill(const Foam::zero) { + // Usually small enough that parallel execution is pointless... for (unsigned i=0; i::readList "reading the single entry" ); - for (unsigned i=0; ifill(elem); } // End of contents marker diff --git a/src/OpenFOAM/containers/Lists/List/List.C b/src/OpenFOAM/containers/Lists/List/List.C index 55ea1f56a5..1b728d37c0 100644 --- a/src/OpenFOAM/containers/Lists/List/List.C +++ b/src/OpenFOAM/containers/Lists/List/List.C @@ -54,7 +54,7 @@ void Foam::List::doResize(const label len) // - when used as storage for DynamicList, it is possible to have // a zero-sized List with a non-null data pointer. - if (this->v_) delete[] this->v_; + delete[] this->v_; this->size_ = len; this->v_ = new T[len]; } @@ -64,7 +64,9 @@ void Foam::List::doResize(const label len) T* nv = new T[len]; - // ie, std::copy(this->v_, this->v_ + overlap, nv); + // Like std::copy(this->v_, this->v_ + overlap, nv); + // but with move semantics! + #ifdef USEMEMCPY if (is_contiguous::value) { @@ -137,12 +139,7 @@ Foam::List::List(const label len, const T& val) if (len) { doAlloc(); - - List_ACCESS(T, (*this), vp); - for (label i=0; i < len; ++i) - { - vp[i] = val; - } + this->fill_uniform(val); } } @@ -163,8 +160,9 @@ Foam::List::List(const label len, const Foam::zero) { doAlloc(); + // fill_uniform() List_ACCESS(T, (*this), vp); - for (label i=0; i < len; ++i) + for (label i = 0; i < len; ++i) { vp[i] = Zero; } @@ -200,109 +198,49 @@ Foam::List::List(const Foam::one, const Foam::zero) template -Foam::List::List(const UList& a) +Foam::List::List(const UList& list) : - UList(nullptr, a.size_) + UList(nullptr, list.size_) { - const label len = this->size_; - - if (len) + if (this->size_ > 0) { doAlloc(); - - #ifdef USEMEMCPY - if (is_contiguous::value) - { - std::memcpy - ( - static_cast(this->v_), a.v_, this->size_bytes() - ); - } - else - #endif - { - List_ACCESS(T, (*this), vp); - List_CONST_ACCESS(T, a, ap); - for (label i = 0; i < len; ++i) - { - vp[i] = ap[i]; - } - } + UList::deepCopy(list); } } template -Foam::List::List(const List& a) +Foam::List::List(const List& list) : - UList(nullptr, a.size_) + UList(nullptr, list.size_) { - const label len = this->size_; - - if (len) + if (this->size_ > 0) { doAlloc(); - - #ifdef USEMEMCPY - if (is_contiguous::value) - { - std::memcpy - ( - static_cast(this->v_), a.v_, this->size_bytes() - ); - } - else - #endif - { - List_ACCESS(T, (*this), vp); - List_CONST_ACCESS(T, a, ap); - for (label i = 0; i < len; ++i) - { - vp[i] = ap[i]; - } - } + UList::deepCopy(list); } } template -Foam::List::List(List& a, bool reuse) +Foam::List::List(List& list, bool reuse) : - UList(nullptr, a.size_) + UList(nullptr, list.size_) { if (reuse) { // Steal content - this->v_ = a.v_; - a.v_ = nullptr; - a.size_ = 0; + this->v_ = list.v_; + list.v_ = nullptr; + list.size_ = 0; return; } - const label len = this->size_; - - if (len) + if (this->size_) { doAlloc(); - - #ifdef USEMEMCPY - if (is_contiguous::value) - { - std::memcpy - ( - static_cast(this->v_), a.v_, this->size_bytes() - ); - } - else - #endif - { - List_ACCESS(T, (*this), vp); - List_CONST_ACCESS(T, a, ap); - for (label i = 0; i < len; ++i) - { - vp[i] = ap[i]; - } - } + UList::deepCopy(list); } } @@ -318,6 +256,7 @@ Foam::List::List(const UList& list, const labelUList& indices) { doAlloc(); + // Copy indirect List_ACCESS(T, (*this), vp); for (label i=0; i < len; ++i) @@ -340,13 +279,16 @@ Foam::List::List { const label len = label(N); - doAlloc(); - - List_ACCESS(T, (*this), vp); - - for (label i=0; i < len; ++i) { - vp[i] = list[indices[i]]; + doAlloc(); + + // Copy indirect + List_ACCESS(T, (*this), vp); + + for (label i = 0; i < len; ++i) + { + vp[i] = list[indices[i]]; + } } } @@ -431,10 +373,7 @@ Foam::List::List(SLList&& list) template Foam::List::~List() { - if (this->v_) - { - delete[] this->v_; - } + delete[] this->v_; } @@ -443,14 +382,16 @@ Foam::List::~List() template void Foam::List::resize(const label len, const T& val) { - label idx = this->size_; + const label oldLen = this->size_; this->doResize(len); - List_ACCESS(T, *this, vp); - while (idx < len) + // Fill trailing part with new values + if (oldLen < this->size_) { - vp[idx] = val; - ++idx; + std::fill + ( + (this->v_ + oldLen), (this->v_ + this->size_), val + ); } } @@ -463,7 +404,7 @@ void Foam::List::transfer(List& list) return; // Self-assignment is a no-op } - // Clear and swap - could also check for self assignment + // Clear and swap clear(); this->size_ = list.size_; this->v_ = list.v_; @@ -489,37 +430,18 @@ void Foam::List::transfer(DynamicList& list) // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template -void Foam::List::operator=(const UList& a) +void Foam::List::operator=(const UList& list) { - if (this == &a) + if (this == &list) { return; // Self-assignment is a no-op } - reAlloc(a.size_); + reAlloc(list.size_); - const label len = this->size_; - - if (len) + if (this->size_ > 0) { - #ifdef USEMEMCPY - if (is_contiguous::value) - { - std::memcpy - ( - static_cast(this->v_), a.v_, this->size_bytes() - ); - } - else - #endif - { - List_ACCESS(T, (*this), vp); - List_CONST_ACCESS(T, a, ap); - for (label i = 0; i < len; ++i) - { - vp[i] = ap[i]; - } - } + UList::deepCopy(list); } } @@ -532,7 +454,12 @@ void Foam::List::operator=(const List& list) return; // Self-assignment is a no-op } - operator=(static_cast&>(list)); + reAlloc(list.size_); + + if (this->size_ > 0) + { + UList::deepCopy(list); + } } @@ -545,6 +472,8 @@ void Foam::List::operator=(const SLList& list) if (len) { + // std::copy(list.begin(), list.end(), this->v_); + T* iter = this->begin(); for (const T& val : list) @@ -582,6 +511,7 @@ void Foam::List::operator=(const IndirectListBase& list) if (len) { + // copyList ... List_ACCESS(T, (*this), vp); for (label i=0; i < len; ++i) diff --git a/src/OpenFOAM/containers/Lists/List/List.H b/src/OpenFOAM/containers/Lists/List/List.H index 0a6cce2a94..b1a398eb67 100644 --- a/src/OpenFOAM/containers/Lists/List/List.H +++ b/src/OpenFOAM/containers/Lists/List/List.H @@ -85,7 +85,7 @@ class List // Discards old storage (if any). Does not copy old contents inline void reAlloc(const label len); - //- Copy all list contents + //- Copy all list contents. Uses operator[] on the input list template inline void copyList(const List2& list); @@ -142,13 +142,13 @@ public: List(const Foam::one, const Foam::zero); //- Copy construct from list - List(const List& a); + List(const List& list); //- Copy construct contents from list - explicit List(const UList& a); + explicit List(const UList& list); //- Construct as copy or re-use as specified - List(List& a, bool reuse); + List(List& list, bool reuse); //- Copy construct subset of list List(const UList& list, const labelUList& indices); diff --git a/src/OpenFOAM/containers/Lists/List/ListI.H b/src/OpenFOAM/containers/Lists/List/ListI.H index 0ae68fbf20..6c8aec1f3e 100644 --- a/src/OpenFOAM/containers/Lists/List/ListI.H +++ b/src/OpenFOAM/containers/Lists/List/ListI.H @@ -55,11 +55,14 @@ template template inline void Foam::List::copyList(const List2& list) { + // NB: operator[] for list read access (eg, an indirect list) + // cannot necessarily replace with std::copy + const label len = this->size_; - for (label i=0; ioperator[](i) = list[i]; + this->v_[i] = list[i]; } } @@ -79,10 +82,13 @@ inline Foam::List::List { doAlloc(); + // Like std::copy() or std::copy_n() + // but without any requirements on the iterator category + InputIterator iter = begIter; for (label i = 0; i < len; ++i) { - this->operator[](i) = *iter; + this->v_[i] = *iter; ++iter; } } @@ -149,6 +155,14 @@ inline void Foam::List::resize_nocopy(const label len) } +// template +// inline void Foam::List::resize_fill(const label len, const T& val) +// { +// this->reAlloc(len); +// this->fill_uniform(val); +// } + + template inline T& Foam::List::newElmt(const label i) { diff --git a/src/OpenFOAM/containers/Lists/List/ListIO.C b/src/OpenFOAM/containers/Lists/List/ListIO.C index 3db5928d19..8faf41238f 100644 --- a/src/OpenFOAM/containers/Lists/List/ListIO.C +++ b/src/OpenFOAM/containers/Lists/List/ListIO.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018-2022 OpenCFD Ltd. + Copyright (C) 2018-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -50,9 +50,6 @@ Foam::Istream& Foam::List::readList(Istream& is) { List& list = *this; - // Anull list - list.clear(); - is.fatalCheck(FUNCTION_NAME); token tok(is); @@ -63,6 +60,7 @@ Foam::Istream& Foam::List::readList(Istream& is) { // Compound: simply transfer contents + list.clear(); // Clear old contents list.transfer ( dynamicCast>> @@ -77,8 +75,8 @@ Foam::Istream& Foam::List::readList(Istream& is) const label len = tok.labelToken(); - // Resize to actual length read - list.resize(len); + // Resize to length required + list.resize_nocopy(len); if (is.format() == IOstreamOption::BINARY && is_contiguous::value) { @@ -96,7 +94,7 @@ Foam::Istream& Foam::List::readList(Istream& is) is.fatalCheck ( "List::readList(Istream&) : " - "reading the binary block" + "reading binary block" ); } } @@ -133,10 +131,8 @@ Foam::Istream& Foam::List::readList(Istream& is) "reading the single entry" ); - for (label i=0; ifill_uniform(elem); } } @@ -148,6 +144,8 @@ Foam::Istream& Foam::List::readList(Istream& is) { // "(...)" : read as SLList and transfer contents + list.clear(); // Clear old contents + is.putBack(tok); // Putback the opening bracket SLList sll(is); // Read as singly-linked list @@ -156,6 +154,8 @@ Foam::Istream& Foam::List::readList(Istream& is) } else { + list.clear(); // Clear old contents + FatalIOErrorInFunction(is) << "incorrect first token, expected or '(', found " << tok.info() << nl diff --git a/src/OpenFOAM/containers/Lists/List/UList.C b/src/OpenFOAM/containers/Lists/List/UList.C index 4a16d82fd3..41ef2c32d5 100644 --- a/src/OpenFOAM/containers/Lists/List/UList.C +++ b/src/OpenFOAM/containers/Lists/List/UList.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2022 OpenCFD Ltd. + Copyright (C) 2017-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -105,35 +105,20 @@ void Foam::UList::swapLast(const label i) template void Foam::UList::deepCopy(const UList& list) { - const label len = this->size_; - - if (len != list.size_) + if (this->size_ != list.size_) { FatalErrorInFunction << "Lists have different sizes: " - << len << " != " << list.size() << nl + << this->size_ << " != " << list.size() << nl << abort(FatalError); } - else if (len) + else if (this->size_ > 0) { - #ifdef USEMEMCPY - if (is_contiguous::value) - { - std::memcpy - ( - static_cast(this->v_), list.v_, this->size_bytes() - ); - } - else - #endif - { - List_ACCESS(T, (*this), lhs); - List_CONST_ACCESS(T, list, rhs); - for (label i = 0; i < len; ++i) - { - lhs[i] = rhs[i]; - } - } + // Can also dispatch with + // - std::execution::parallel_unsequenced_policy + // - std::execution::unsequenced_policy + + std::copy(list.cbegin(), list.cend(), this->v_); } } @@ -142,17 +127,19 @@ template template void Foam::UList::deepCopy(const IndirectListBase& list) { - const label len = this->size_; - - if (len != list.size()) + if (this->size_ != list.size()) { FatalErrorInFunction << "Lists have different sizes: " - << len << " != " << list.size() << nl + << this->size_ << " != " << list.size() << nl << abort(FatalError); } - else if (len) + else if (this->size_) { + // copyList() + + const label len = this->size_; + List_ACCESS(T, (*this), lhs); for (label i = 0; i < len; ++i) { @@ -164,28 +151,15 @@ void Foam::UList::deepCopy(const IndirectListBase& list) // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // -template -void Foam::UList::operator=(const T& val) -{ - const label len = this->size(); - - List_ACCESS(T, (*this), vp); - - for (label i=0; i < len; ++i) - { - vp[i] = val; - } -} - - template void Foam::UList::operator=(const Foam::zero) { + // fill_uniform() const label len = this->size(); List_ACCESS(T, (*this), vp); - for (label i=0; i < len; ++i) + for (label i = 0; i < len; ++i) { vp[i] = Zero; } diff --git a/src/OpenFOAM/containers/Lists/List/UList.H b/src/OpenFOAM/containers/Lists/List/UList.H index 01d5d1b562..45caa1bc0c 100644 --- a/src/OpenFOAM/containers/Lists/List/UList.H +++ b/src/OpenFOAM/containers/Lists/List/UList.H @@ -118,6 +118,10 @@ protected: //- always addresses a valid section of the list. labelRange validateRange(const labelRange& requestedRange) const; + //- Assign all entries to the given value + // Caution: method name subject to change + inline void fill_uniform(const T& val); + //- No copy assignment (default: shallow copy) // // Assignment may need to be shallow (copy pointer) @@ -347,7 +351,7 @@ public: // Copy //- Copy the pointer and size held by the given UList - inline void shallowCopy(const UList& list); + inline void shallowCopy(const UList& list) noexcept; //- Copy elements of the given UList. Sizes must match! void deepCopy(const UList& list); @@ -390,7 +394,7 @@ public: inline operator const Foam::List&() const; //- Assignment of all entries to the given value - void operator=(const T& val); + inline void operator=(const T& val); //- Assignment of all entries to zero void operator=(const Foam::zero); @@ -468,7 +472,7 @@ public: static constexpr label max_size() noexcept { return labelMax; } //- Swap content with another UList of the same type in constant time - inline void swap(UList& list); + inline void swap(UList& list) noexcept; // STL member operators @@ -703,15 +707,12 @@ template struct Hash> : UList::hasher {}; -//- Object access operator or list access operator. +//- Object access operator or list access operator (default is pass-through) //- \sa ListListOps::combine() template struct accessOp { - const T& operator()(const T& obj) const - { - return obj; // Default is pass-through - } + const T& operator()(const T& obj) const { return obj; } }; @@ -719,10 +720,7 @@ struct accessOp template struct emptyOp { - bool operator()(const T& obj) const - { - return obj.empty(); - } + bool operator()(const T& obj) const { return obj.empty(); } }; @@ -730,10 +728,7 @@ struct emptyOp template struct sizeOp { - label operator()(const T& obj) const - { - return obj.size(); - } + label operator()(const T& obj) const { return obj.size(); } }; diff --git a/src/OpenFOAM/containers/Lists/List/UListI.H b/src/OpenFOAM/containers/Lists/List/UListI.H index 183b5e6893..a56999a068 100644 --- a/src/OpenFOAM/containers/Lists/List/UListI.H +++ b/src/OpenFOAM/containers/Lists/List/UListI.H @@ -27,6 +27,7 @@ License \*---------------------------------------------------------------------------*/ #include "error.H" +// already included by stdFoam.H // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -46,6 +47,25 @@ inline Foam::UList::UList(T* __restrict__ v, const label len) noexcept {} +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template +inline void Foam::UList::fill_uniform(const T& val) +{ + // Can also dispatch with + // - std::execution::parallel_unsequenced_policy + // - std::execution::unsequenced_policy + + if (this->size_ > 0) + { + std::fill_n + ( + this->v_, this->size_, val + ); + } +} + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template @@ -268,7 +288,7 @@ inline bool Foam::UList::contains(const T& val, label pos) const template -inline void Foam::UList::shallowCopy(const UList& list) +inline void Foam::UList::shallowCopy(const UList& list) noexcept { size_ = list.size_; v_ = list.v_; @@ -277,6 +297,13 @@ inline void Foam::UList::shallowCopy(const UList& list) // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // +template +inline void Foam::UList::operator=(const T& val) +{ + this->fill_uniform(val); +} + + namespace Foam { // Template specialization for bool @@ -439,7 +466,7 @@ inline void Foam::UList::setAddressableSize(const label n) noexcept template -inline void Foam::UList::swap(UList& list) +inline void Foam::UList::swap(UList& list) noexcept { if (&list == this) { diff --git a/src/OpenFOAM/containers/Lists/List/UListIO.C b/src/OpenFOAM/containers/Lists/List/UListIO.C index 80285f51a9..36ccdd4a4f 100644 --- a/src/OpenFOAM/containers/Lists/List/UListIO.C +++ b/src/OpenFOAM/containers/Lists/List/UListIO.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2022 OpenCFD Ltd. + Copyright (C) 2016-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -264,10 +264,8 @@ Foam::Istream& Foam::UList::readList(Istream& is) "reading the single entry" ); - for (label i=0; ifill_uniform(elem); } }