STYLE: check tmp with is_reference() or movable(), instead of isTmp()

- missed consistency in a few places.

- return nullptr (with automatic conversion to tmp) on failures
  instead of tmp<....>(nullptr), for cleaner coding.

INT: add support for an 'immovable' tmp pointer

- this idea is from openfoam.org, to allow creation of a tmp that is
  protected from having its memory reclaimed in field operations

ENH: tmp NewImmovable factory method, forwards as immovable/movable
This commit is contained in:
Mark Olesen
2023-03-14 10:58:46 +01:00
parent 13bd644cf4
commit e68acbe314
24 changed files with 187 additions and 118 deletions

View File

@ -63,6 +63,7 @@ class refPtr
enum refType
{
PTR, //!< A managed pointer (not ref-counted)
REF_Types, //!< Magic value (ptr: less-than, ref: greater than)
CREF, //!< A const reference to an object
REF //!< A non-const reference to an object
};
@ -175,13 +176,13 @@ public:
bool good() const noexcept { return bool(ptr_); }
//- If the stored/referenced content is const
bool is_const() const noexcept { return (type_ == CREF); }
inline bool is_const() const noexcept;
//- True if this is a managed pointer (not a reference)
bool is_pointer() const noexcept { return (type_ == PTR); }
inline bool is_pointer() const noexcept;
//- True if this is a reference (not a pointer)
bool is_reference() const noexcept { return (type_ != PTR); }
inline bool is_reference() const noexcept;
//- True if this is a non-null managed pointer
inline bool movable() const noexcept;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 OpenFOAM Foundation
Copyright (C) 2018-2022 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -64,7 +64,6 @@ inline constexpr Foam::refPtr<T>::refPtr(T* p) noexcept
{}
template<class T>
inline constexpr Foam::refPtr<T>::refPtr(const T& obj) noexcept
:
@ -190,17 +189,40 @@ inline Foam::refPtr<T>::~refPtr() noexcept
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
inline bool Foam::refPtr<T>::is_const() const noexcept
{
return (type_ == CREF);
}
template<class T>
inline bool Foam::refPtr<T>::is_pointer() const noexcept
{
//OR: return (type_ == PTR);
return (type_ < REF_Types);
}
template<class T>
inline bool Foam::refPtr<T>::is_reference() const noexcept
{
//OR: return (type_ == CREF || type_ == REF);
return (type_ > REF_Types);
}
template<class T>
inline bool Foam::refPtr<T>::movable() const noexcept
{
return (is_pointer() && ptr_);
return (ptr_ && is_pointer());
}
template<class T>
inline const T& Foam::refPtr<T>::cref() const
{
if (is_pointer() && !ptr_)
if (!ptr_ && is_pointer())
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -221,7 +243,7 @@ inline T& Foam::refPtr<T>::ref() const
<< this->typeName()
<< abort(FatalError);
}
else if (is_pointer() && !ptr_)
else if (!ptr_ && is_pointer())
{
FatalErrorInFunction
<< this->typeName() << " deallocated"

View File

@ -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.
@ -34,6 +34,8 @@ Description
and a shared_ptr without ref-counting and null deleter.
This allows the tmp to double as a pointer management and an indirect
pointer to externally allocated objects.
In contrast to std::shared_ptr, only a limited number of tmp items
will ever share a pointer.
SourceFiles
tmpI.H
@ -73,6 +75,8 @@ class tmp
enum refType
{
PTR, //!< A managed pointer (ref-counted)
CACHE_PTR, //!< A managed pointer (ref-counted), but immovable
REF_Types, //!< Magic value (ptr: less-than, ref: greater than)
CREF, //!< A const reference to an object
REF //!< A non-const reference to an object
};
@ -86,9 +90,8 @@ class tmp
// Private Member Functions
//- Increment the ref-count for a managed pointer
//- and check that it is not oversubscribed
inline void incrCount();
//- Fatal if ref-count of a managed pointer is oversubscribed
inline void checkUseCount() const;
public:
@ -117,6 +120,10 @@ public:
//- Construct, taking ownership of the pointer.
inline explicit tmp(T* p);
//- Construct, taking ownership of the pointer,
//- with specified protection against moving.
inline tmp(bool immovable, T* p);
//- Implicit construct for a const reference to an object.
inline constexpr tmp(const T& obj) noexcept;
@ -166,6 +173,19 @@ public:
return tmp<T>(new T(std::forward<Args>(args)...));
}
//- Construct movable/immovable tmp with forwarding arguments
// \param immovable create as non-movable pointer
// \param args list of arguments with which an instance of T
// will be constructed.
//
// \note Similar to std::make_shared, but the overload for
// array types is not disabled.
template<class... Args>
static tmp<T> NewImmovable(bool immovable, Args&&... args)
{
return tmp<T>(immovable, new T(std::forward<Args>(args)...));
}
//- Construct tmp from derived type with forwarding arguments
// \param args list of arguments with which an instance of U
// will be constructed.
@ -191,13 +211,13 @@ public:
bool good() const noexcept { return bool(ptr_); }
//- If the stored/referenced content is const
bool is_const() const noexcept { return (type_ == CREF); }
inline bool is_const() const noexcept;
//- True if this is a managed pointer (not a reference)
bool is_pointer() const noexcept { return (type_ == PTR); }
inline bool is_pointer() const noexcept;
//- True if this is a reference (not a pointer)
bool is_reference() const noexcept { return (type_ != PTR); }
inline bool is_reference() const noexcept;
//- True if this is a non-null managed pointer with a unique ref-count
inline bool movable() const noexcept;
@ -239,9 +259,13 @@ public:
//- Clear existing and transfer ownership.
inline void reset(tmp<T>&& other) noexcept;
//- Delete managed temporary object and set to new given pointer
//- Delete managed temporary object and set to new given pointer.
inline void reset(T* p = nullptr) noexcept;
//- Delete managed temporary object and set to new given pointer,
//- with specified protection against moving.
inline void reset(bool immovable, T* p) noexcept;
//- Avoid inadvertent casting (to object or pointer)
void reset(const autoPtr<T>&) = delete;
@ -330,8 +354,10 @@ public:
//- Identical to good(), or bool operator
bool valid() const noexcept { return bool(ptr_); }
//- Identical to is_pointer()
bool isTmp() const noexcept { return type_ == PTR; }
//- Identical to is_pointer(). Prefer is_pointer() or movable().
//
// \deprecated(2020-07) - prefer is_pointer() or movable()
bool isTmp() const noexcept { return is_pointer(); }
//- Deprecated(2020-07) True if a null managed pointer
//

View File

@ -29,23 +29,6 @@ License
#include "error.H"
#include <typeinfo>
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class T>
inline void Foam::tmp<T>::incrCount()
{
ptr_->refCount::operator++();
if (ptr_->refCount::use_count() > 1)
{
FatalErrorInFunction
<< "Attempt to create more than 2 tmp's referring to the same"
" object of type tmp<" << typeid(T).name() << '>'
<< abort(FatalError);
}
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class T>
@ -55,6 +38,23 @@ inline Foam::word Foam::tmp<T>::typeName()
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class T>
inline void Foam::tmp<T>::checkUseCount() const
{
if (ptr_ && ptr_->refCount::use_count() > 1)
{
FatalErrorInFunction
<< "Attempt to create more than "
<< (ptr_->refCount::use_count() + 1)
<< " tmp's referring to the same object of type tmp<"
<< typeid(T).name() << '>'
<< abort(FatalError);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T>
@ -90,6 +90,15 @@ inline Foam::tmp<T>::tmp(T* p)
}
template<class T>
inline Foam::tmp<T>::tmp(bool immovable, T* p)
:
tmp<T>(p)
{
if (ptr_ && immovable) type_ = CACHE_PTR;
}
template<class T>
inline constexpr Foam::tmp<T>::tmp(const T& obj) noexcept
:
@ -130,7 +139,8 @@ inline Foam::tmp<T>::tmp(const tmp<T>& rhs)
{
if (ptr_)
{
this->incrCount();
ptr_->refCount::operator++();
this->checkUseCount();
}
else
{
@ -160,7 +170,8 @@ inline Foam::tmp<T>::tmp(const tmp<T>& rhs, bool reuse)
}
else
{
this->incrCount();
ptr_->refCount::operator++();
this->checkUseCount();
}
}
else
@ -192,17 +203,40 @@ inline Foam::tmp<T>::~tmp() noexcept
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
inline bool Foam::tmp<T>::is_const() const noexcept
{
return (type_ == CREF);
}
template<class T>
inline bool Foam::tmp<T>::is_pointer() const noexcept
{
//OR: return (type_ == PTR || type_ == CACHE_PTR);
return (type_ < REF_Types);
}
template<class T>
inline bool Foam::tmp<T>::is_reference() const noexcept
{
//OR: return (type_ == CREF || type_ == REF);
return (type_ > REF_Types);
}
template<class T>
inline bool Foam::tmp<T>::movable() const noexcept
{
return (is_pointer() && ptr_ && ptr_->refCount::unique());
return (ptr_ && type_ == PTR && ptr_->refCount::unique());
}
template<class T>
inline const T& Foam::tmp<T>::cref() const
{
if (is_pointer() && !ptr_)
if (!ptr_ && is_pointer())
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -223,7 +257,7 @@ inline T& Foam::tmp<T>::ref() const
<< this->typeName()
<< abort(FatalError);
}
else if (is_pointer() && !ptr_)
else if (!ptr_ && is_pointer())
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -244,7 +278,7 @@ inline T* Foam::tmp<T>::ptr() const
<< abort(FatalError);
}
if (is_pointer())
if (type_ == PTR)
{
if (!ptr_->refCount::unique())
{
@ -262,6 +296,7 @@ inline T* Foam::tmp<T>::ptr() const
return p;
}
// CACHE_PTR (immovable) is cloned, as per a reference
return ptr_->clone().ptr();
}
@ -269,7 +304,7 @@ inline T* Foam::tmp<T>::ptr() const
template<class T>
inline void Foam::tmp<T>::clear() const noexcept
{
if (is_pointer() && ptr_)
if (ptr_ && is_pointer())
{
if (ptr_->refCount::unique())
{
@ -293,6 +328,14 @@ inline void Foam::tmp<T>::reset(T* p) noexcept
}
template<class T>
inline void Foam::tmp<T>::reset(bool immovable, T* p) noexcept
{
reset(p);
if (ptr_ && immovable) type_ = CACHE_PTR;
}
template<class T>
inline void Foam::tmp<T>::reset(tmp<T>&& other) noexcept
{
@ -382,7 +425,7 @@ inline void Foam::tmp<T>::swap(tmp<T>& other) noexcept
template<class T>
inline const T* Foam::tmp<T>::operator->() const
{
if (is_pointer() && !ptr_)
if (!ptr_ && is_pointer())
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -403,7 +446,7 @@ inline T* Foam::tmp<T>::operator->()
<< this->typeName()
<< abort(FatalError);
}
else if (is_pointer() && !ptr_)
else if (!ptr_ && is_pointer())
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -428,7 +471,7 @@ inline void Foam::tmp<T>::operator=(const tmp<T>& other)
if (other.is_pointer())
{
ptr_ = other.ptr_;
type_ = PTR;
type_ = other.type_;
other.ptr_ = nullptr;
other.type_ = PTR;

View File

@ -134,8 +134,7 @@ Foam::fv::atmAmbientTurbSource::atmAmbientTurbSource
else
{
FatalErrorInFunction
<< "Unable to find neither epsilon nor omega field." << nl
<< "atmAmbientTurbSource needs either epsilon or omega field."
<< "Needs either epsilon or omega field."
<< abort(FatalError);
}

View File

@ -226,8 +226,7 @@ Foam::fv::atmBuoyancyTurbSource::atmBuoyancyTurbSource
else
{
FatalErrorInFunction
<< "Unable to find neither epsilon nor omega field." << nl
<< "atmBuoyancyTurbSource needs either epsilon or omega field."
<< "Needs either epsilon or omega field."
<< abort(FatalError);
}

View File

@ -161,8 +161,7 @@ Foam::fv::atmLengthScaleTurbSource::atmLengthScaleTurbSource
else
{
FatalErrorInFunction
<< "Unable to find neither epsilon nor omega field." << nl
<< "atmLengthScaleTurbSource needs either epsilon or omega field."
<< "Needs either epsilon or omega field."
<< abort(FatalError);
}

View File

@ -123,8 +123,9 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource
tmp<volScalarField> tepsilon = turbPtr->epsilon();
tmp<volScalarField> tomega = turbPtr->omega();
if (!tepsilon.isTmp())
if (tepsilon.is_reference())
{
isEpsilon_ = true;
fieldNames_[0] = tepsilon().name();
const dictionary& turbDict = turbPtr->coeffDict();
@ -132,7 +133,7 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource
C1_.read("C1", turbDict);
C2_.read("C2", turbDict);
}
else if (!tomega.isTmp())
else if (tomega.is_reference())
{
isEpsilon_ = false;
fieldNames_[0] = tomega().name();
@ -143,8 +144,7 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource
else
{
FatalErrorInFunction
<< "Unable to find neither epsilon nor omega field." << nl
<< "atmPlantCanopyTurbSource needs either epsilon or omega field."
<< "Needs either epsilon or omega field."
<< abort(FatalError);
}

View File

@ -49,7 +49,7 @@ uncorrectedLnGrad<Type>::correction
) const
{
NotImplemented;
return tmp<GeometricField<Type, faePatchField, edgeMesh>>(nullptr);
return nullptr;
}

View File

@ -40,18 +40,18 @@ Foam::tmp<Foam::volVectorField> Foam::constrainHbyA
{
tmp<volVectorField> tHbyANew;
if (tHbyA.isTmp())
if (tHbyA.movable())
{
tHbyANew = tHbyA;
tHbyANew.ref().rename("HbyA");
}
else
{
tHbyANew = new volVectorField("HbyA", tHbyA);
// Clone and use given name
tHbyANew.reset(new volVectorField("HbyA", tHbyA));
}
volVectorField& HbyA = tHbyANew.ref();
volVectorField::Boundary& HbyAbf = HbyA.boundaryFieldRef();
auto& HbyAbf = tHbyANew.ref().boundaryFieldRef();
forAll(U.boundaryField(), patchi)
{

View File

@ -50,7 +50,7 @@ orthogonalSnGrad<Type>::correction
) const
{
NotImplemented;
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>(nullptr);
return nullptr;
}

View File

@ -172,15 +172,11 @@ public:
return false;
}
//- Return the explicit correction to the snGrad
//- for the given field
//- Return the explicit correction to the snGrad for the given field
virtual tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
correction(const GeometricField<Type, fvPatchField, volMesh>&) const
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
return nullptr;
}
//- Return the snGrad of the given cell field

View File

@ -50,7 +50,7 @@ uncorrectedSnGrad<Type>::correction
) const
{
NotImplemented;
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>(nullptr);
return nullptr;
}

View File

@ -315,10 +315,7 @@ public:
}
else
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
return nullptr;
}
}
};

View File

@ -342,10 +342,7 @@ public:
}
else
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
return nullptr;
}
}
};

View File

@ -242,10 +242,7 @@ public:
}
else
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
return nullptr;
}
}

View File

@ -222,10 +222,7 @@ public:
}
else
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
return nullptr;
}
}
};

View File

@ -234,10 +234,7 @@ public:
}
else
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
return nullptr;
}
}
};

View File

@ -238,10 +238,7 @@ public:
}
else
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
return nullptr;
}
}
};

View File

@ -203,10 +203,7 @@ public:
virtual tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
correction(const GeometricField<Type, fvPatchField, volMesh>&) const
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
return nullptr;
}
//- Return the face-interpolate of the given cell field

View File

@ -98,8 +98,8 @@ Foam::DispersionRASModel<CloudType>::DispersionRASModel
:
DispersionModel<CloudType>(owner),
kPtr_(nullptr),
ownK_(false),
epsilonPtr_(nullptr),
ownK_(false),
ownEpsilon_(false)
{}
@ -112,8 +112,8 @@ Foam::DispersionRASModel<CloudType>::DispersionRASModel
:
DispersionModel<CloudType>(dm),
kPtr_(dm.kPtr_),
ownK_(dm.ownK_),
epsilonPtr_(dm.epsilonPtr_),
ownK_(dm.ownK_),
ownEpsilon_(dm.ownEpsilon_)
{
dm.ownK_ = false;
@ -138,20 +138,22 @@ void Foam::DispersionRASModel<CloudType>::cacheFields(const bool store)
if (store)
{
tmp<volScalarField> tk = this->kModel();
if (tk.isTmp())
if (tk.movable())
{
// Take ownership
kPtr_ = tk.ptr();
ownK_ = true;
}
else
{
kPtr_ = &tk();
kPtr_ = &tk.cref();
ownK_ = false;
}
tmp<volScalarField> tepsilon = this->epsilonModel();
if (tepsilon.isTmp())
if (tepsilon.movable())
{
// Take ownership
epsilonPtr_ = tepsilon.ptr();
ownEpsilon_ = true;
}
@ -163,12 +165,12 @@ void Foam::DispersionRASModel<CloudType>::cacheFields(const bool store)
}
else
{
if (ownK_ && kPtr_)
if (ownK_)
{
deleteDemandDrivenData(kPtr_);
ownK_ = false;
}
if (ownEpsilon_ && epsilonPtr_)
if (ownEpsilon_)
{
deleteDemandDrivenData(epsilonPtr_);
ownEpsilon_ = false;

View File

@ -60,13 +60,13 @@ protected:
//- Turbulence k
const volScalarField* kPtr_;
//- Take ownership of the k field
mutable bool ownK_;
//- Turbulence epsilon
const volScalarField* epsilonPtr_;
//- Take ownership of the epsilon field
//- Local ownership of the k field
mutable bool ownK_;
//- Local ownership of the epsilon field
mutable bool ownEpsilon_;

View File

@ -77,8 +77,8 @@ Foam::BrownianMotionForce<CloudType>::BrownianMotionForce
ParticleForce<CloudType>(owner, mesh, dict, typeName, true),
rndGen_(owner.rndGen()),
lambda_(this->coeffs().getScalar("lambda")),
turbulence_(this->coeffs().getBool("turbulence")),
kPtr_(nullptr),
turbulence_(this->coeffs().getBool("turbulence")),
ownK_(false)
{}
@ -92,8 +92,8 @@ Foam::BrownianMotionForce<CloudType>::BrownianMotionForce
ParticleForce<CloudType>(bmf),
rndGen_(bmf.rndGen_),
lambda_(bmf.lambda_),
turbulence_(bmf.turbulence_),
kPtr_(nullptr),
turbulence_(bmf.turbulence_),
ownK_(false)
{}
@ -102,7 +102,9 @@ Foam::BrownianMotionForce<CloudType>::BrownianMotionForce
template<class CloudType>
Foam::BrownianMotionForce<CloudType>::~BrownianMotionForce()
{}
{
cacheFields(false);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -115,20 +117,21 @@ void Foam::BrownianMotionForce<CloudType>::cacheFields(const bool store)
if (store)
{
tmp<volScalarField> tk = kModel();
if (tk.isTmp())
if (tk.movable())
{
// Take ownership
kPtr_ = tk.ptr();
ownK_ = true;
}
else
{
kPtr_ = &tk();
kPtr_ = &tk.cref();
ownK_ = false;
}
}
else
{
if (ownK_ && kPtr_)
if (ownK_)
{
deleteDemandDrivenData(kPtr_);
ownK_ = false;

View File

@ -65,7 +65,7 @@ class BrownianMotionForce
:
public ParticleForce<CloudType>
{
// Private data
// Private Data
//- Reference to the cloud random number generator
Random& rndGen_;
@ -73,13 +73,13 @@ class BrownianMotionForce
//- Molecular free path length [m]
const scalar lambda_;
//- Turbulence flag
bool turbulence_;
//- Pointer to the turbulence kinetic energy field
const volScalarField* kPtr_;
//- Flag that indicates ownership of turbulence k field
//- Turbulence flag
bool turbulence_;
//- Local ownership of the turbulence k field
bool ownK_;