From b4703f4a08f42f0ff9b182f38d457be148c92226 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Sun, 4 Mar 2018 21:38:33 +0100 Subject: [PATCH] ENH: pre-cleanup of Xfer class (issue #639) - This class is largely a pre-C++11 holdover, prior to having movable references. - align internals with autoPtr instead of always unconditionally allocating memory. The valid() method can be used to check for a null pointer. - Consolidate into a single file, in anticipation of future removal. --- applications/test/xfer1/Make/files | 3 - applications/test/xfer1/Make/options | 0 applications/test/xfer1/Test-xfer1.C | 233 --------------------------- src/OpenFOAM/memory/Xfer/Xfer.H | 127 +++++++++------ src/OpenFOAM/memory/Xfer/XferI.H | 186 --------------------- 5 files changed, 78 insertions(+), 471 deletions(-) delete mode 100644 applications/test/xfer1/Make/files delete mode 100644 applications/test/xfer1/Make/options delete mode 100644 applications/test/xfer1/Test-xfer1.C delete mode 100644 src/OpenFOAM/memory/Xfer/XferI.H diff --git a/applications/test/xfer1/Make/files b/applications/test/xfer1/Make/files deleted file mode 100644 index 10a272c0273..00000000000 --- a/applications/test/xfer1/Make/files +++ /dev/null @@ -1,3 +0,0 @@ -Test-xfer1.C - -EXE = $(FOAM_USER_APPBIN)/Test-xfer1 diff --git a/applications/test/xfer1/Make/options b/applications/test/xfer1/Make/options deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/applications/test/xfer1/Test-xfer1.C b/applications/test/xfer1/Test-xfer1.C deleted file mode 100644 index f1fe7c0674e..00000000000 --- a/applications/test/xfer1/Test-xfer1.C +++ /dev/null @@ -1,233 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Application - -Description - -\*---------------------------------------------------------------------------*/ - -#include "OSspecific.H" - -#include "IOstreams.H" -#include "labelList.H" -#include "DynamicList.H" -#include "face.H" -#include "pointField.H" -#include "DynamicField.H" - -using namespace Foam; - - -template<class Type> -void printInfo(const Xfer<Type>& xf) -{ - Info<<" address:" << long(xf.get()) << nl - <<" isNull = " << isNull(xf) << nl - <<" notNull = " << notNull(xf) << nl - <<" valid() = " << xf.valid() << nl; -} - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -// Main program: - -int main(int argc, char *argv[]) -{ - labelList lstA(10); - labelList lstC - { - 1, 2, 3, 4 - }; - - forAll(lstA, i) - { - lstA[i] = 5 - i; - } - - // Information about null-object - - Info<<"nullObject:" << nl; - printInfo(Xfer<labelList>::null()); - { - // This probably needs more work... - Xfer<labelList> xf = Xfer<labelList>::null(); - - Info<<"copy of nullObject:" << nl; - printInfo(xf); - } - - Info<< "lstA: " << lstA << nl - << "lstC: " << lstC << nl; - - Xfer<labelList> xA = xferMove(lstA); - Xfer<labelList> xB; - - labelList lstB( xA ); - - Info<< "xA: " << xA() << nl - << "xB: " << xB() << nl - << "lstA: " << lstA << nl - << "lstB: " << lstB << nl - << "lstC: " << lstC << nl; - - // Now illegal: xA = lstB; - - xA->transfer(lstB); - - Info<< "xA: " << xA() << nl - << "xB: " << xB() << nl - << "lstA: " << lstA << nl - << "lstB: " << lstB << nl - << "lstC: " << lstC << nl; - - xB = xA; - - // Construct with forwarding. For this example, truly ugly. - Xfer<labelList> xFwdA = - Xfer<labelList>::New - ( - std::initializer_list<label> - { - 1, 2, 10, 20, 15, 24, 200 - } - ); - - Xfer<labelList> xFwdB = Xfer<labelList>::New(label(8), 123); - Xfer<labelList> xFwdC = Xfer<labelList>::New(); - - Info<< nl - << "Constructed with forwarding: " << nl - << *xFwdA << nl - << *xFwdB << nl - << *xFwdC << nl - << nl; - - - labelList lstD(xferCopy(lstC)); - labelList lstE(xferMove(lstC)); - - // this must be empty - labelList lstF = xferCopy(lstC); - - Info<< "xA: " << xA() << nl - << "xB: " << xB() << nl - << "lstA: " << lstA << nl - << "lstB: " << lstB << nl - << "lstC: " << lstC << nl - << "lstD: " << lstD << nl - << "lstE: " << lstE << nl - << "lstF: " << lstF << nl; - - Info<< "xB[" << xB->size() << "]\n"; - - // clear the underlying List - xB->clear(); - - Info<< "xB[" << xB->size() << "]\n"; - - DynamicList<label> dl; - for (label i = 0; i < 5; ++i) - { - dl.append(i); - } - - face f1(dl); - face f2(xferCopy<labelList>(dl)); - - Info<< "dl[" << dl.size() << "/" << dl.capacity() << "] " << dl << nl; - Info<< "f1: " << f1 << nl; - Info<< "f2: " << f2 << nl; - - // add some more labels - for (label i = 5; i < 8; ++i) - { - dl.append(i); - } - - // note: xfer() method returns a plain labelList - face f3(dl.xfer()); - Info<< "dl[" << dl.size() << "/" << dl.capacity() << "] " << dl << nl; - Info<< "f3: " << f3 << nl; - - Info<<"\nflip faces:" << nl; - f1.flip(); - f3.flip(); - Info<< "f1: " << f1 << nl; - Info<< "f3: " << f3 << nl; - - - { - Info<<"\nTest xfer with fields:" << nl; - List<point> list1 - { - { 0, 1, 2 }, - { 3, 4, 5 }, - { 6, 7, 8 }, - { 9, 10, 11 }, - }; - - // Field from Xfer<List> - pointField field1(list1.xfer()); - Info<<nl - << "xfer construct from List" << nl - <<"input (list) = " << list1 << nl - <<"output (field) = " << field1 << nl; - - - // Field from Xfer<List> ... again - pointField field2(field1.xfer()); - Info<<nl - <<"xfer construct from Field (as List): " << nl - <<"input (field) = " << field1 << nl - <<"output (field) = " << field2 << nl; - - - // Field from Xfer<Field> - pointField field3(xferMove(field2)); - Info<<nl - <<"xfer construct from Field (as Field): " << nl - <<"input (field) = " << field2 << nl - <<"output (field) = " << field3 << nl; - - - // Field from Xfer<Field> .. again - pointField field4(xferCopy(field3)); - Info<<nl - <<"xfer copy construct from Field (as Field): " << nl - <<"input (field) = " << field3 << nl - <<"output (field) = " << field4 << nl; - - - DynamicField<point> dyfield1(xferCopy(field4)); - Info<<nl - <<"xfer copy construct from Field (as Field): " << nl - <<"input (field) = " << field4 << nl - <<"output (dyn-field) = " << dyfield1 << nl; - } - - return 0; -} - - -// ************************************************************************* // diff --git a/src/OpenFOAM/memory/Xfer/Xfer.H b/src/OpenFOAM/memory/Xfer/Xfer.H index 07371b19abc..b9519ccf6dd 100644 --- a/src/OpenFOAM/memory/Xfer/Xfer.H +++ b/src/OpenFOAM/memory/Xfer/Xfer.H @@ -30,35 +30,24 @@ Description The wrapped object of type \<T\> must implement a transfer() method and an operator=() copy method. - Since it is decided upon construction of the Xfer object whether the - parameter is to be copied or transferred, the contents of the resulting - Xfer object can be transferred unconditionally. This greatly simplifies - defining constructors or methods in other classes with mixed - transfer/copy semantics without requiring 2^N different versions. +\deprecated This class is an artifact from pre-C++11 code (MAR-2018). - When transferring between dissimilar types, the xferCopyTo() and - xferMoveTo() functions can prove useful. An example is transferring - from a DynamicList to a List. - - \code - List<label> list1; - DynamicList<label> list2; - ... - - SomeClass obj(xferCopy(list1), xferMoveTo<labelList>(list1)); - \endcode +Note + This class is an artifact from pre-C++11 code, where it was used + as a workaround for the lack of movable references (rvalue). + The interfaces previously using Xfer to reclaim memory now use + movable references directly or, in the rare case, an autoPtr. See also xferCopy, xferCopyTo, xferMove, xferMoveTo -SourceFiles - XferI.H - \*---------------------------------------------------------------------------*/ #ifndef Xfer_H #define Xfer_H +#include "nullObject.H" + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam @@ -87,57 +76,81 @@ public: // Constructors + //- Construct with no managed object. + inline constexpr Xfer() noexcept : ptr_(nullptr) + {} + //- Store object pointer and manage its deletion // Can also be used later to transfer by assignment - inline explicit Xfer(T* p = nullptr); + inline explicit Xfer(T* p) noexcept : ptr_(p) + {} - //- Construct, transferring its contents - inline Xfer(const Xfer<T>& xf); + //- Move construct, transferring ownership + inline Xfer(const Xfer<T>& xf) noexcept : ptr_(xf.ptr_) + { + xf.ptr_ = nullptr; + } //- Destructor - inline ~Xfer(); + inline ~Xfer() noexcept + { + delete ptr_; + ptr_ = nullptr; + } // Static Member Functions //- Return a null object reference - inline static const Xfer<T>& null(); - - //- Construct new Xfer container with forwarding arguments to T - template<class... Args> - inline static Xfer<T> New(Args&&... args); + inline static const Xfer<T>& null() + { + return NullObjectRef<Xfer<T>>(); + } // Member Functions - //- Test for valid pointer and not a nullObject reference. - inline bool valid() const; + //- Test for valid pointer + inline bool valid() const noexcept { return ptr_; } //- Pointer to the underlying object. - inline T* get() const; + inline T* get() const noexcept { return ptr_; } //- Rvalue reference to the underlying object. - inline T&& rvalue() const; + inline T&& rvalue() const { return std::move(*ptr_); } //- Swaps the managed objects - inline void swap(Xfer<T>& other) noexcept; + inline void swap(Xfer<T>& other) noexcept + { + T* p = ptr_; + ptr_ = other.ptr_; + other.ptr_ = p; + } // Member Operators - //- Transfer contents into the object - inline void operator=(const Xfer<T>& xf); - //- Reference to the underlying object - inline T& operator*() const; + inline T& operator*() const { return *ptr_; } //- Pointer to the underlying object - inline T* operator->() const; + inline T* operator->() const { return ptr_; } //- Reference to the underlying object - inline T& operator()() const; - + inline T& operator()() const { return *ptr_; } + + //- Move assignment, transferring ownership + inline void operator=(const Xfer<T>& rhs) noexcept + { + if (this != &rhs) + { + // clear and swap + delete ptr_; + ptr_ = rhs.ptr_; + rhs.ptr_ = nullptr; + } + } }; @@ -145,26 +158,41 @@ public: //- Copy construct contents of the \a obj -// +// \deprecated - Xfer should not be used in new code // \sa xferCopyTo, xferMove, xferMoveTo and Foam::Xfer template<class T> -inline Xfer<T> xferCopy(const T& obj); +inline Xfer<T> xferCopy(const T& obj) +{ + return Foam::Xfer<T>(new T(obj)); +} + //- Transfer construct contents of the \a obj +// \deprecated - Xfer should not be used in new code // // \sa xferCopy, xferCopyTo, xferMoveTo and Foam::Xfer template<class T> -inline Xfer<T> xferMove(T& obj); +inline Xfer<T> xferMove(T& obj) +{ + T* ptr = new T; + ptr->transfer(obj); + return Foam::Xfer<T>(ptr); +} //- Copy construct contents of the \a obj from dissimilar type +// \deprecated - Xfer should not be used in new code // // \sa xferCopy, xferMove, xferMoveTo and Foam::Xfer template<class T, class From> -inline Xfer<T> xferCopyTo(const From& obj); +inline Xfer<T> xferCopyTo(const From& obj) +{ + return Foam::Xfer<T>(new T(obj)); +} //- Transfer construct contents of the \a obj from dissimilar type +// \deprecated - Xfer should not be used in new code // // \par Example Use // \code @@ -175,7 +203,12 @@ inline Xfer<T> xferCopyTo(const From& obj); // // \sa xferCopy, xferCopyTo, xferMove and Foam::Xfer template<class T, class From> -inline Xfer<T> xferMoveTo(From& obj); +inline Xfer<T> xferMoveTo(From& obj) +{ + T* ptr = new T; + ptr->transfer(obj); + return Foam::Xfer<T>(ptr); +} // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -184,10 +217,6 @@ inline Xfer<T> xferMoveTo(From& obj); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -#include "XferI.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - #endif // ************************************************************************* // diff --git a/src/OpenFOAM/memory/Xfer/XferI.H b/src/OpenFOAM/memory/Xfer/XferI.H deleted file mode 100644 index f203ff074dc..00000000000 --- a/src/OpenFOAM/memory/Xfer/XferI.H +++ /dev/null @@ -1,186 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -\*---------------------------------------------------------------------------*/ - -#include "nullObject.H" -#include <utility> - -// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * // - -template<class T> -inline const Foam::Xfer<T>& Foam::Xfer<T>::null() -{ - return NullObjectRef<Xfer<T>>(); -} - - -template<class T> -template<class... Args> -inline Foam::Xfer<T> Foam::Xfer<T>::New(Args&&... args) -{ - return Xfer<T>(new T(std::forward<Args>(args)...)); -} - - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -template<class T> -inline Foam::Xfer<T>::Xfer(T* p) -: - ptr_(p ? p : new T) -{} - - -template<class T> -inline Foam::Xfer<T>::Xfer(const Xfer<T>& xf) -: - ptr_(new T) -{ - T* p = xf.get(); - - if (p && Foam::notNull(p)) - { - ptr_->transfer(*p); - } -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -template<class T> -inline bool Foam::Xfer<T>::valid() const -{ - return (ptr_ && Foam::notNull(ptr_)); -} - - -template<class T> -inline T* Foam::Xfer<T>::get() const -{ - return ptr_; -} - - -template<class T> -inline T&& Foam::Xfer<T>::rvalue() const -{ - // Need check for valid() ? - return std::move(*ptr_); -} - - -template<class T> -inline void Foam::Xfer<T>::swap(Xfer<T>& other) noexcept -{ - // Swap pointers - T* p = ptr_; - ptr_ = other.ptr; - other.ptr_ = p; -} - - -// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - -template<class T> -inline Foam::Xfer<T>::~Xfer() -{ - if (ptr_ && Foam::notNull(ptr_)) - { - delete ptr_; - } - ptr_ = nullptr; -} - - -// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // - -template<class T> -inline void Foam::Xfer<T>::operator=(const Xfer<T>& xf) -{ - // Silently ignore attempted copy to self - if (this != &xf) - { - ptr_->transfer(*xf); - } -} - - -template<class T> -inline T& Foam::Xfer<T>::operator*() const -{ - return *ptr_; -} - - -template<class T> -inline T* Foam::Xfer<T>::operator->() const -{ - return ptr_; -} - - -template<class T> -inline T& Foam::Xfer<T>::operator()() const -{ - return *ptr_; -} - - -// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // - -template<class T> -inline Foam::Xfer<T> Foam::xferCopy(const T& obj) -{ - T* ptr = new T(obj); - return Foam::Xfer<T>(ptr); -} - - -template<class T, class From> -inline Foam::Xfer<T> Foam::xferCopyTo(const From& obj) -{ - T* ptr = new T(obj); - return Foam::Xfer<T>(ptr); -} - - -template<class T> -inline Foam::Xfer<T> Foam::xferMove(T& obj) -{ - T* ptr = new T; - ptr->transfer(obj); - return Foam::Xfer<T>(ptr); -} - - -template<class T, class From> -inline Foam::Xfer<T> Foam::xferMoveTo(From& obj) -{ - T* ptr = new T; - ptr->transfer(obj); - return Foam::Xfer<T>(ptr); -} - - -// ************************************************************************* // -- GitLab