From 96c9bf8615a56c72b6492bfe10ab72e8e2ee5aa0 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Mon, 25 Sep 2023 10:58:13 +0200 Subject: [PATCH] ENH: add List::resize_unsafe(label) - changes the addressed list size without affecting list allocation. Can be useful for the following type of coding pattern: - pre-allocate a List with some max content length - populate with some content (likely not the entire pre-allocated size) - truncate the list to the length of valid content - process the List - discard the List Since the List is being discarded, using resize_unsafe() instead of resize() avoids an additional allocation with the new size and copying/moving of the elements. This programming pattern can also be used when the List is being returned from a subroutine, and carrying about a bit of unused memory is less important than avoiding reallocation + copy/move. If used improperly, it can obviously result in addressing into unmanaged memory regions (ie, 'unsafe'). --- .../test/DynamicList/Test-DynamicList.C | 26 +++++++++++++++++++ applications/test/List/Test-List.C | 11 +++++++- src/OpenFOAM/containers/Lists/List/List.H | 7 +++++ src/OpenFOAM/containers/Lists/List/ListI.H | 7 +++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/applications/test/DynamicList/Test-DynamicList.C b/applications/test/DynamicList/Test-DynamicList.C index 659bce8a98..5f9e8b63fe 100644 --- a/applications/test/DynamicList/Test-DynamicList.C +++ b/applications/test/DynamicList/Test-DynamicList.C @@ -348,6 +348,32 @@ int main(int argc, char *argv[]) Info<< "input = " << flatOutput(input1) << nl << "remove " << range << " = " << flatOutput(list1) << nl; } + + { + input1 = identity(5); + list1 = identity(4, 5); + list1.reserve(10); + + Info<< nl << "test swap(List)" << nl; + Info<< " input: " << input1.size() + << '/' << input1.capacity() << ' ' + << flatOutput(input1) << nl; + Info<< " list: " << list1.size() << '/' + << list1.capacity() << ' ' + << flatOutput(list1) << nl; + + + // input1.swap(list1); // This is wrong! + list1.swap(input1); // Correct + + Info<< "after swap:" << nl; + Info<< " input: " << input1.size() + << '/' << input1.capacity() << ' ' + << flatOutput(input1) << nl; + Info<< " list: " << list1.size() << '/' + << list1.capacity() << ' ' + << flatOutput(list1) << nl; + } } Info<< "\nEnd\n"; diff --git a/applications/test/List/Test-List.C b/applications/test/List/Test-List.C index 03e77dcfef..50b094d7a6 100644 --- a/applications/test/List/Test-List.C +++ b/applications/test/List/Test-List.C @@ -169,8 +169,17 @@ 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) { diff --git a/src/OpenFOAM/containers/Lists/List/List.H b/src/OpenFOAM/containers/Lists/List/List.H index 6289e29758..e22e88e6ce 100644 --- a/src/OpenFOAM/containers/Lists/List/List.H +++ b/src/OpenFOAM/containers/Lists/List/List.H @@ -227,6 +227,13 @@ 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); } diff --git a/src/OpenFOAM/containers/Lists/List/ListI.H b/src/OpenFOAM/containers/Lists/List/ListI.H index 621ecd19d6..6bab28191b 100644 --- a/src/OpenFOAM/containers/Lists/List/ListI.H +++ b/src/OpenFOAM/containers/Lists/List/ListI.H @@ -185,6 +185,13 @@ inline void Foam::List::resize_nocopy(const label len) } +template +inline void Foam::List::resize_unsafe(const label len) noexcept +{ + UList::setAddressableSize(len); +} + + template inline T& Foam::List::newElmt(const label i) {