From 4110699d90962efc9fad362d2825435da5a56304 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Mon, 27 Jul 2020 07:50:53 +0200 Subject: [PATCH] ENH: HashTable::emplace_set() method, HashPtrTable support for unique_ptr - forwarding like the emplace() method, but overwriting existing entries as required - propagate similar changes to HashPtrTable For example, with HashPtrTable table(...) : With 'insert' semantics table.emplace("list1", 1000); vs if (!table.found("list1")) { table.set("list1", new labelList(1000)); } or table.insert("list1", autoPtr::New(1000)); Note that the last example invokes an unnecessary allocation/deletion if the insertion is unsuccessful. With 'set' semantics: table.emplace_set("list1", 15); vs table.set("list1", new labelList(15)); --- .../test/HashPtrTable/Test-HashPtrTable.C | 73 ++++++++++++++++++- .../test/HashTable2/Test-HashTable2.C | 6 +- .../HashTables/HashPtrTable/HashPtrTable.H | 21 +++++- .../HashTables/HashPtrTable/HashPtrTableI.H | 59 ++++++++++++++- .../HashTables/HashTable/HashTable.H | 5 ++ .../HashTables/HashTable/HashTableI.H | 14 +++- 6 files changed, 172 insertions(+), 6 deletions(-) diff --git a/applications/test/HashPtrTable/Test-HashPtrTable.C b/applications/test/HashPtrTable/Test-HashPtrTable.C index 48840f0e40..1003b0b992 100644 --- a/applications/test/HashPtrTable/Test-HashPtrTable.C +++ b/applications/test/HashPtrTable/Test-HashPtrTable.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011 OpenFOAM Foundation - Copyright (C) 2017-2019 OpenCFD Ltd. + Copyright (C) 2017-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,6 +35,45 @@ Description using namespace Foam; +class Scalar +{ + scalar data_; + +public: + + Scalar() + : + data_(0) + {} + + Scalar(scalar val) + : + data_(val) + {} + + ~Scalar() + { + Info<<"delete Scalar: " << data_ << endl; + } + + const scalar& value() const + { + return data_; + } + + scalar& value() + { + return data_; + } + + friend Ostream& operator<<(Ostream& os, const Scalar& val) + { + os << val.data_; + return os; + } +}; + + template void printTable(const HashPtrTable& table) { @@ -147,6 +186,38 @@ int main() Info<<"old" << nl; printTable(moved); + + Info<< "Verifying deletion characteristics" << nl; + { + HashPtrTable tbl; + tbl.set("abc", new Scalar(42.1)); + tbl.set("def", nullptr); + tbl.set("pi", new Scalar(3.14159)); + tbl.set("natlog", new Scalar(2.718282)); + tbl.insert("sqrt2", autoPtr::New(1.414214)); + + Info<< "Table: " << tbl << nl; + + Info<< nl << "... overwrite again" << nl; + + tbl.set("abc", new Scalar(42.1)); + tbl.set("def", nullptr); + tbl.set("pi", new Scalar(3.14159)); + tbl.set("natlog", new Scalar(2.718282)); + + tbl.emplace("other", 15.6); + + Info<< "Table: " << tbl << nl; + + Info << nl << "Test emplace and emplace_set" << nl; + + tbl.emplace("abc", 100); + tbl.emplace_set("def", 100); + tbl.emplace_set("other", 100); + + Info<< "Table: " << tbl << nl; + } + return 0; } diff --git a/applications/test/HashTable2/Test-HashTable2.C b/applications/test/HashTable2/Test-HashTable2.C index 4093ca4f42..010251f807 100644 --- a/applications/test/HashTable2/Test-HashTable2.C +++ b/applications/test/HashTable2/Test-HashTable2.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -252,8 +252,10 @@ int main(int argc, char *argv[]) ltable1.insert("abc", identity(2)); ltable1.insert("def", identity(3)); ltable1.insert("ghi", identity(4)); - ltable1.emplace("jkl", 10, -35); + ltable1.emplace("jkl", label(10), -35); ltable1.emplace("mno"); + ltable1.emplace("def", label(2), -2); // no overwrite + ltable1.emplace_set("ghi", label(2), -2); // overwrite labelList list1(identity(4, -4)); diff --git a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.H b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.H index 49ed149991..bd43a25530 100644 --- a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.H +++ b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2018 OpenCFD Ltd. + Copyright (C) 2017-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -41,6 +41,7 @@ SourceFiles #define HashPtrTable_H #include "HashTable.H" +#include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -172,6 +173,16 @@ public: // Override HashTable methods + //- Emplace insert a new entry, not overwriting existing entries. + // \return True if the entry did not previously exist in the table. + template + inline bool emplace(const Key& key, Args&&... args); + + //- Emplace set an entry, overwriting any existing entries. + // \return True, since it always overwrites any entries. + template + inline bool emplace_set(const Key& key, Args&&... args); + //- No insert() with raw pointers (potential memory leaks). //- Use insert() with autoPtr or set() inline bool insert(const Key&, T*) = delete; @@ -186,6 +197,11 @@ public: // \return True if the entry inserted (not previously in table) inline bool insert(const Key& key, autoPtr&& ptr); + //- Insert a new entry, not overwriting existing entries. + // + // \return True if the entry inserted (not previously in table) + inline bool insert(const Key& key, std::unique_ptr&& ptr); + //- Assign a new entry, overwriting existing entries. inline bool set(const Key& key, T* ptr); @@ -194,6 +210,9 @@ public: //- Assign a new entry, overwriting existing entries. inline bool set(const Key& key, autoPtr&& ptr); + + //- Assign a new entry, overwriting existing entries. + inline bool set(const Key& key, std::unique_ptr&& ptr); }; diff --git a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTableI.H b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTableI.H index 485f618b82..d15e8bf50f 100644 --- a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTableI.H +++ b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTableI.H @@ -45,6 +45,52 @@ inline Foam::HashPtrTable::HashPtrTable(const label size) // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template +template +inline bool Foam::HashPtrTable::emplace +( + const Key& key, + Args&&... args +) +{ + // Use insertion semantics + return + ( + !parent_type::found(key) + && this->parent_type::set(key, new T(std::forward(args)...)) + ); +} + + +template +template +inline bool Foam::HashPtrTable::emplace_set +( + const Key& key, + Args&&... args +) +{ + return this->set(key, new T(std::forward(args)...)); +} + + +template +inline bool Foam::HashPtrTable::insert +( + const Key& key, + autoPtr& ptr +) +{ + if (parent_type::insert(key, ptr.get())) + { + ptr.release(); // Now owned by HashPtrTable + return true; + } + + return false; +} + + template inline bool Foam::HashPtrTable::insert ( @@ -66,7 +112,7 @@ template inline bool Foam::HashPtrTable::insert ( const Key& key, - autoPtr&& ptr + std::unique_ptr&& ptr ) { if (parent_type::insert(key, ptr.get())) @@ -112,4 +158,15 @@ inline bool Foam::HashPtrTable::set } +template +inline bool Foam::HashPtrTable::set +( + const Key& key, + std::unique_ptr&& ptr +) +{ + return this->set(key, ptr.release()); +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H index 89605dae69..8e2a2e4561 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H @@ -364,6 +364,11 @@ public: template inline bool emplace(const Key& key, Args&&... args); + //- Emplace set an entry, overwriting any existing entries. + // \return True, since it always overwrites any entries. + template + inline bool emplace_set(const Key& key, Args&&... args); + //- Copy insert a new entry, not overwriting existing entries. // \return True if the entry did not previously exist in the table. inline bool insert(const Key& key, const T& obj); diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H index 5487726066..ab96a64b94 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2019 OpenCFD Ltd. + Copyright (C) 2017-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -163,6 +163,18 @@ inline bool Foam::HashTable::emplace } +template +template +inline bool Foam::HashTable::emplace_set +( + const Key& key, + Args&&... args +) +{ + return this->setEntry(true, key, std::forward(args)...); +} + + template inline bool Foam::HashTable::insert (