ENH: cleanup tmp class (issue #639)

Improve alignment of its behaviour with std::shared_ptr

  - element_type typedef
  - swap, reset methods

* additional reference access methods:

cref()
    returns a const reference, synonymous with operator().
    This provides a more verbose alternative to using the '()' operator
    when that is desired.

        Mnemonic: a const form of 'ref()'

constCast()
    returns a non-const reference, regardless if the underlying object
    itself is a managed pointer or a const object.
    This is similar to ref(), but more permissive.

        Mnemonic: const_cast<>

    Using the constCast() method greatly reduces the amount of typing
    and reading. And since the data type is already defined via the tmp
    template parameter, the type deduction is automatically known.

    Previously,

        const tmp<volScalarField>& tfld;

        const_cast<volScalarField&>(tfld()).rename("name");
        volScalarField& fld = const_cast<volScalarField&>(tfld());

    Now,

        tfld.constCast().rename("name");
        auto& fld = tfld.constCast();

--

BUG: attempts to move tmp value that may still be shared.

- old code simply checked isTmp() to decide if the contents could be
  transfered. However, this means that the content of a shared tmp
  would be removed, leaving other instances without content.

* movable() method checks that for a non-null temporary that is
  unique (not shared).
This commit is contained in:
Mark Olesen
2018-02-26 12:05:00 +01:00
parent 660f3e5492
commit 52b36f84b5
41 changed files with 1034 additions and 815 deletions

View File

@ -0,0 +1,3 @@
Test-tmp.C
EXE = $(FOAM_USER_APPBIN)/Test-tmp

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -22,10 +22,10 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
tmpFieldTest
Test-tmp
Description
Tests for possible memory leaks in the tmp<Field> algebra.
Tests for possible memory leaks in the tmp (and tmp<Field> algebra).
\*---------------------------------------------------------------------------*/
@ -33,19 +33,50 @@ Description
using namespace Foam;
struct myScalarField : public scalarField
{
using scalarField::scalarField;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main()
{
scalarField f1(1000000, 1.0), f2(1000000, 2.0), f3(1000000, 3.0);
for (;;)
{
f1 = f2 + f3 + f2 + f3;
scalarField f1(1000000, 1.0), f2(1000000, 2.0), f3(1000000, 3.0);
for (int iter=0; iter < 50; ++iter)
{
f1 = f2 + f3 + f2 + f3;
}
Info<<"f1 = " << f1 << nl;
}
Info<< "end" << endl;
{
tmp<scalarField> tfld1 = tmp<scalarField>::New(20, Zero);
Info<< "tmp refCount = " << tfld1->count() << nl;
if (tfld1.valid())
{
Info<<"tmp: " << tfld1() << nl;
}
}
{
tmp<scalarField> tfld2 =
tmp<scalarField>::NewFrom<myScalarField>(20, Zero);
Info<< "tmp refCount = " << tfld2->count() << nl;
if (tfld2.valid())
{
Info<<"tmp: " << tfld2() << nl;
}
}
Info<< "\nEnd" << endl;
}

View File

@ -1,3 +0,0 @@
Test-tmpField.C
EXE = $(FOAM_USER_APPBIN)/Test-tmpField

View File

@ -217,12 +217,8 @@ DimensionedField<Type, GeoMesh>::DimensionedField
const tmp<DimensionedField<Type, GeoMesh>>& tdf
)
:
regIOobject(tdf(), tdf.isTmp()),
Field<Type>
(
const_cast<DimensionedField<Type, GeoMesh>&>(tdf()),
tdf.isTmp()
),
regIOobject(tdf.constCast(), tdf.movable()),
Field<Type>(tdf.constCast(), tdf.movable()),
mesh_(tdf().mesh_),
dimensions_(tdf().dimensions_),
oriented_(tdf().oriented_)
@ -318,11 +314,7 @@ DimensionedField<Type, GeoMesh>::DimensionedField
)
:
regIOobject(newName, tdf(), true),
Field<Type>
(
const_cast<DimensionedField<Type, GeoMesh>&>(tdf()),
tdf.isTmp()
),
Field<Type>(tdf.constCast(), tdf.movable()),
mesh_(tdf().mesh_),
dimensions_(tdf().dimensions_),
oriented_(tdf().oriented_)
@ -511,7 +503,7 @@ void DimensionedField<Type, GeoMesh>::operator=
const tmp<DimensionedField<Type, GeoMesh>>& tdf
)
{
const DimensionedField<Type, GeoMesh>& df = tdf();
auto& df = tdf.constCast();
// Check for assignment to self
if (this == &df)
@ -525,7 +517,7 @@ void DimensionedField<Type, GeoMesh>::operator=
dimensions_ = df.dimensions();
oriented_ = df.oriented();
this->transfer(const_cast<DimensionedField<Type, GeoMesh>&>(df));
this->transfer(df);
tdf.clear();
}

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,32 +41,31 @@ tmp<DimensionedField<TypeR, GeoMesh>> New
const dimensionSet& dimensions
)
{
DimensionedField<TypeR, GeoMesh>& df1 =
const_cast<DimensionedField<TypeR, GeoMesh>&>(tdf1());
if (tdf1.isTmp())
{
auto& df1 = tdf1.constCast();
df1.rename(name);
df1.dimensions().reset(dimensions);
return tdf1;
}
else
{
return tmp<DimensionedField<TypeR, GeoMesh>>
const auto& df1 = tdf1();
return tmp<DimensionedField<TypeR, GeoMesh>>
(
new DimensionedField<TypeR, GeoMesh>
(
new DimensionedField<TypeR, GeoMesh>
IOobject
(
IOobject
(
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
@ -82,7 +81,7 @@ public:
const dimensionSet& dimensions
)
{
const DimensionedField<Type1, GeoMesh>& df1 = tdf1();
const auto& df1 = tdf1();
return tmp<DimensionedField<TypeR, GeoMesh>>
(
@ -114,32 +113,31 @@ public:
const dimensionSet& dimensions
)
{
DimensionedField<TypeR, GeoMesh>& df1 =
const_cast<DimensionedField<TypeR, GeoMesh>&>(tdf1());
if (tdf1.isTmp())
{
auto& df1 = tdf1.constCast();
df1.rename(name);
df1.dimensions().reset(dimensions);
return tdf1;
}
else
{
return tmp<DimensionedField<TypeR, GeoMesh>>
const auto& df1 = tdf1();
return tmp<DimensionedField<TypeR, GeoMesh>>
(
new DimensionedField<TypeR, GeoMesh>
(
new DimensionedField<TypeR, GeoMesh>
IOobject
(
IOobject
(
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
};
@ -157,7 +155,7 @@ public:
const dimensionSet& dimensions
)
{
const DimensionedField<Type1, GeoMesh>& df1 = tdf1();
const auto& df1 = tdf1();
return tmp<DimensionedField<TypeR, GeoMesh>>
(
@ -190,33 +188,31 @@ public:
const dimensionSet& dimensions
)
{
const DimensionedField<Type1, GeoMesh>& df1 = tdf1();
DimensionedField<TypeR, GeoMesh>& df2 =
const_cast<DimensionedField<TypeR, GeoMesh>&>(tdf2());
if (tdf2.isTmp())
{
auto& df2 = tdf2.constCast();
df2.rename(name);
df2.dimensions().reset(dimensions);
return tdf2;
}
else
{
return tmp<DimensionedField<TypeR, GeoMesh>>
const auto& df1 = tdf1();
return tmp<DimensionedField<TypeR, GeoMesh>>
(
new DimensionedField<TypeR, GeoMesh>
(
new DimensionedField<TypeR, GeoMesh>
IOobject
(
IOobject
(
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
};
@ -234,32 +230,31 @@ public:
const dimensionSet& dimensions
)
{
DimensionedField<TypeR, GeoMesh>& df1 =
const_cast<DimensionedField<TypeR, GeoMesh>&>(tdf1());
if (tdf1.isTmp())
{
auto& df1 = tdf1.constCast();
df1.rename(name);
df1.dimensions().reset(dimensions);
return tdf1;
}
else
{
return tmp<DimensionedField<TypeR, GeoMesh>>
const auto& df1 = tdf1();
return tmp<DimensionedField<TypeR, GeoMesh>>
(
new DimensionedField<TypeR, GeoMesh>
(
new DimensionedField<TypeR, GeoMesh>
IOobject
(
IOobject
(
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
};
@ -277,40 +272,39 @@ public:
const dimensionSet& dimensions
)
{
DimensionedField<TypeR, GeoMesh>& df1 =
const_cast<DimensionedField<TypeR, GeoMesh>&>(tdf1());
DimensionedField<TypeR, GeoMesh>& df2 =
const_cast<DimensionedField<TypeR, GeoMesh>&>(tdf2());
if (tdf1.isTmp())
{
auto& df1 = tdf1.constCast();
df1.rename(name);
df1.dimensions().reset(dimensions);
return tdf1;
}
else if (tdf2.isTmp())
{
auto& df2 = tdf2.constCast();
df2.rename(name);
df2.dimensions().reset(dimensions);
return tdf2;
}
else
{
return tmp<DimensionedField<TypeR, GeoMesh>>
const auto& df1 = tdf1();
return tmp<DimensionedField<TypeR, GeoMesh>>
(
new DimensionedField<TypeR, GeoMesh>
(
new DimensionedField<TypeR, GeoMesh>
IOobject
(
IOobject
(
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
name,
df1.instance(),
df1.db()
),
df1.mesh(),
dimensions
)
);
}
};

View File

@ -160,11 +160,7 @@ FieldField<Field, Type>::FieldField(const PtrList<Field<Type>>& tl)
template<template<class> class Field, class Type>
FieldField<Field, Type>::FieldField(const tmp<FieldField<Field, Type>>& tf)
:
PtrList<Field<Type>>
(
const_cast<FieldField<Field, Type>&>(tf()),
tf.isTmp()
)
PtrList<Field<Type>>(tf.constCast(), tf.movable())
{
tf.clear();
}

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -44,20 +44,18 @@ tmp<FieldField<Field, TypeR>> New
{
return tf1;
}
else
tmp<FieldField<Field, TypeR>> rtf
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
if (initRet)
{
tmp<FieldField<Field, TypeR>> rtf
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
if (initRet)
{
rtf.ref() = tf1();
}
return rtf;
rtf.ref() = tf1();
}
return rtf;
}
@ -93,13 +91,11 @@ public:
{
return tf1;
}
else
{
return tmp<FieldField<Field, TypeR>>
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
}
return tmp<FieldField<Field, TypeR>>
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
}
};
@ -145,13 +141,11 @@ public:
{
return tf2;
}
else
{
return tmp<FieldField<Field, TypeR>>
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
}
return tmp<FieldField<Field, TypeR>>
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
}
};
@ -171,13 +165,11 @@ public:
{
return tf1;
}
else
{
return tmp<FieldField<Field, TypeR>>
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
}
return tmp<FieldField<Field, TypeR>>
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
}
};
@ -201,13 +193,11 @@ public:
{
return tf2;
}
else
{
return tmp<FieldField<Field, TypeR>>
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
}
return tmp<FieldField<Field, TypeR>>
(
FieldField<Field, TypeR>::NewCalculatedType(tf1())
);
}
};

View File

@ -256,7 +256,7 @@ Foam::Field<Type>::Field(const UIndirectList<Type>& list)
template<class Type>
Foam::Field<Type>::Field(const tmp<Field<Type>>& tf)
:
List<Type>(const_cast<Field<Type>&>(tf()), tf.isTmp())
List<Type>(tf.constCast(), tf.movable())
{
tf.clear();
}

View File

@ -44,17 +44,15 @@ tmp<Field<TypeR>> New
{
return tf1;
}
else
tmp<Field<TypeR>> rtf(new Field<TypeR>(tf1().size()));
if (initRet)
{
tmp<Field<TypeR>> rtf(new Field<TypeR>(tf1().size()));
if (initRet)
{
rtf.ref() = tf1();
}
return rtf;
rtf.ref() = tf1();
}
return rtf;
}
@ -81,10 +79,8 @@ public:
{
return tf1;
}
else
{
return tmp<Field<TypeR>>(new Field<TypeR>(tf1().size()));
}
return tmp<Field<TypeR>>(new Field<TypeR>(tf1().size()));
}
};
@ -120,10 +116,8 @@ public:
{
return tf2;
}
else
{
return tmp<Field<TypeR>>(new Field<TypeR>(tf1().size()));
}
return tmp<Field<TypeR>>(new Field<TypeR>(tf1().size()));
}
};
@ -143,10 +137,8 @@ public:
{
return tf1;
}
else
{
return tmp<Field<TypeR>>(new Field<TypeR>(tf1().size()));
}
return tmp<Field<TypeR>>(new Field<TypeR>(tf1().size()));
}
};
@ -170,10 +162,8 @@ public:
{
return tf2;
}
else
{
return tmp<Field<TypeR>>(new Field<TypeR>(tf1().size()));
}
return tmp<Field<TypeR>>(new Field<TypeR>(tf1().size()));
}
};

View File

@ -455,11 +455,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
)
:
Internal
(
const_cast<GeometricField<Type, PatchField, GeoMesh>&>(tgf()),
tgf.isTmp()
),
Internal(tgf.constCast(), tgf.movable()),
timeIndex_(tgf().timeIndex()),
field0Ptr_(nullptr),
fieldPrevIterPtr_(nullptr),
@ -517,12 +513,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
)
:
Internal
(
io,
const_cast<GeometricField<Type, PatchField, GeoMesh>&>(tgf()),
tgf.isTmp()
),
Internal(io, tgf.constCast(), tgf.movable()),
timeIndex_(tgf().timeIndex()),
field0Ptr_(nullptr),
fieldPrevIterPtr_(nullptr),
@ -581,12 +572,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
)
:
Internal
(
newName,
const_cast<GeometricField<Type, PatchField, GeoMesh>&>(tgf()),
tgf.isTmp()
),
Internal(newName, tgf.constCast(), tgf.movable()),
timeIndex_(tgf().timeIndex()),
field0Ptr_(nullptr),
fieldPrevIterPtr_(nullptr),
@ -690,12 +676,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const wordList& actualPatchTypes
)
:
Internal
(
io,
const_cast<GeometricField<Type, PatchField, GeoMesh>&>(tgf()),
tgf.isTmp()
),
Internal(io, tgf.constCast(), tgf.movable()),
timeIndex_(tgf().timeIndex()),
field0Ptr_(nullptr),
fieldPrevIterPtr_(nullptr),
@ -1221,7 +1202,7 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator=
this->dimensions() = gf.dimensions();
this->oriented() = gf.oriented();
if (tgf.isTmp())
if (tgf.movable())
{
// Transfer the storage from the tmp
primitiveFieldRef().transfer

View File

@ -125,16 +125,16 @@ public:
// Constructors
//- Construct from a BoundaryMesh
Boundary(const BoundaryMesh&);
Boundary(const BoundaryMesh& bmesh);
//- Construct from a BoundaryMesh,
// reference to the internal field
// and a patch type
Boundary
(
const BoundaryMesh&,
const Internal&,
const word&
const BoundaryMesh& bmesh,
const Internal& field,
const word& patchFieldType
);
//- Construct from a BoundaryMesh,
@ -143,8 +143,8 @@ public:
// types (to override constraint patches)
Boundary
(
const BoundaryMesh&,
const Internal&,
const BoundaryMesh& bmesh,
const Internal& field,
const wordList& wantedPatchTypes,
const wordList& actualPatchTypes = wordList()
);
@ -154,16 +154,16 @@ public:
// and a PtrList<PatchField<Type>>
Boundary
(
const BoundaryMesh&,
const Internal&,
const BoundaryMesh& bmesh,
const Internal& field,
const PtrList<PatchField<Type>>&
);
//- Construct as copy setting the reference to the internal field
Boundary
(
const Internal&,
const Boundary&
const Internal& field,
const Boundary& btf
);
//- Construct as copy
@ -173,14 +173,14 @@ public:
// BoundaryField for which such operations are unavailable.
Boundary
(
const Boundary&
const Boundary& btf
);
//- Construct from dictionary
Boundary
(
const BoundaryMesh&,
const Internal&,
const BoundaryMesh& bmesh,
const Internal& field,
const dictionary&
);

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -45,9 +45,8 @@ bool reusable(const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf)
{
if (GeometricField<Type, PatchField, GeoMesh>::debug)
{
const GeometricField<Type, PatchField, GeoMesh>& gf = tgf();
const typename GeometricField<Type, PatchField, GeoMesh>::
Boundary& gbf = gf.boundaryField();
const auto& gf = tgf();
const auto& gbf = gf.boundaryField();
forAll(gbf, patchi)
{
@ -68,10 +67,8 @@ bool reusable(const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf)
return true;
}
else
{
return false;
}
return false;
}
@ -84,39 +81,38 @@ tmp<GeometricField<TypeR, PatchField, GeoMesh>> New
const bool initRet = false
)
{
GeometricField<TypeR, PatchField, GeoMesh>& gf1 =
const_cast<GeometricField<TypeR, PatchField, GeoMesh>&>(tgf1());
if (reusable(tgf1))
{
auto& gf1 = tgf1.constCast();
gf1.rename(name);
gf1.dimensions().reset(dimensions);
return tgf1;
}
else
{
tmp<GeometricField<TypeR, PatchField, GeoMesh>> rtgf
const auto& gf1 = tgf1();
tmp<GeometricField<TypeR, PatchField, GeoMesh>> rtgf
(
new GeometricField<TypeR, PatchField, GeoMesh>
(
new GeometricField<TypeR, PatchField, GeoMesh>
IOobject
(
IOobject
(
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
if (initRet)
{
rtgf.ref() == tgf1();
}
return rtgf;
if (initRet)
{
rtgf.ref() == gf1;
}
return rtgf;
}
@ -138,7 +134,7 @@ public:
const dimensionSet& dimensions
)
{
const GeometricField<Type1, PatchField, GeoMesh>& gf1 = tgf1();
const auto& gf1 = tgf1();
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
(
@ -170,32 +166,31 @@ public:
const dimensionSet& dimensions
)
{
GeometricField<TypeR, PatchField, GeoMesh>& gf1 =
const_cast<GeometricField<TypeR, PatchField, GeoMesh>&>(tgf1());
if (reusable(tgf1))
{
auto& gf1 = tgf1.constCast();
gf1.rename(name);
gf1.dimensions().reset(dimensions);
return tgf1;
}
else
{
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
const auto& gf1 = tgf1();
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
(
new GeometricField<TypeR, PatchField, GeoMesh>
(
new GeometricField<TypeR, PatchField, GeoMesh>
IOobject
(
IOobject
(
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
}
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
}
};
@ -221,7 +216,7 @@ public:
const dimensionSet& dimensions
)
{
const GeometricField<Type1, PatchField, GeoMesh>& gf1 = tgf1();
const auto& gf1 = tgf1();
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
(
@ -262,33 +257,31 @@ public:
const dimensionSet& dimensions
)
{
const GeometricField<Type1, PatchField, GeoMesh>& gf1 = tgf1();
GeometricField<TypeR, PatchField, GeoMesh>& gf2 =
const_cast<GeometricField<TypeR, PatchField, GeoMesh>&>(tgf2());
if (reusable(tgf2))
{
auto& gf2 = tgf2.constCast();
gf2.rename(name);
gf2.dimensions().reset(dimensions);
return tgf2;
}
else
{
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
const auto& gf1 = tgf1();
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
(
new GeometricField<TypeR, PatchField, GeoMesh>
(
new GeometricField<TypeR, PatchField, GeoMesh>
IOobject
(
IOobject
(
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
}
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
}
};
@ -312,32 +305,31 @@ public:
const dimensionSet& dimensions
)
{
GeometricField<TypeR, PatchField, GeoMesh>& gf1 =
const_cast<GeometricField<TypeR, PatchField, GeoMesh>&>(tgf1());
if (reusable(tgf1))
{
auto& gf1 = tgf1.constCast();
gf1.rename(name);
gf1.dimensions().reset(dimensions);
return tgf1;
}
else
{
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
const auto& gf1 = tgf1();
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
(
new GeometricField<TypeR, PatchField, GeoMesh>
(
new GeometricField<TypeR, PatchField, GeoMesh>
IOobject
(
IOobject
(
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
}
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
}
};
@ -355,40 +347,39 @@ public:
const dimensionSet& dimensions
)
{
GeometricField<TypeR, PatchField, GeoMesh>& gf1 =
const_cast<GeometricField<TypeR, PatchField, GeoMesh>&>(tgf1());
GeometricField<TypeR, PatchField, GeoMesh>& gf2 =
const_cast<GeometricField<TypeR, PatchField, GeoMesh>&>(tgf2());
if (reusable(tgf1))
{
auto& gf1 = tgf1.constCast();
gf1.rename(name);
gf1.dimensions().reset(dimensions);
return tgf1;
}
else if (reusable(tgf2))
{
auto& gf2 = tgf2.constCast();
gf2.rename(name);
gf2.dimensions().reset(dimensions);
return tgf2;
}
else
{
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
const auto& gf1 = tgf1();
return tmp<GeometricField<TypeR, PatchField, GeoMesh>>
(
new GeometricField<TypeR, PatchField, GeoMesh>
(
new GeometricField<TypeR, PatchField, GeoMesh>
IOobject
(
IOobject
(
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
}
name,
gf1.instance(),
gf1.db()
),
gf1.mesh(),
dimensions
)
);
}
};

View File

@ -98,15 +98,13 @@ Foam::lduMatrix::faceH(const Field<Type>& psi) const
return tfaceHpsi;
}
else
{
FatalErrorInFunction
<< "Cannot calculate faceH"
" the matrix does not have any off-diagonal coefficients."
<< exit(FatalError);
return tmp<Field<Type>>(nullptr);
}
FatalErrorInFunction
<< "Cannot calculate faceH"
" the matrix does not have any off-diagonal coefficients."
<< exit(FatalError);
return tmp<Field<Type>>();
}

View File

@ -53,6 +53,10 @@ class refCount
public:
//- A non-counting (dummy) refCount
struct zero {};
// Constructors
//- Construct null initializing count to 0

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,14 +25,19 @@ Class
Foam::tmp
Description
A class for managing temporary objects
A class for managing temporary objects.
This is a combination of std::shared_ptr (with intrusive ref-counting)
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.
SourceFiles
tmpI.H
See also
Foam::refCount
Foam::autoPtr
Foam::refCount
\*---------------------------------------------------------------------------*/
@ -41,6 +46,7 @@ See also
#include "refCount.H"
#include "word.H"
#include <utility>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -57,111 +63,201 @@ class tmp
// Private data
//- Object types
enum type
enum refType
{
TMP,
CONST_REF
PTR, //!< Managing a (ref-counted) pointer
CREF //!< Using a const-reference to an object
};
//- Pointer to object
//- The managed pointer or the address of const-reference object
mutable T* ptr_;
//- Type of object
type type_;
//- The type (managed pointer | const-reference object)
mutable refType type_;
// Private member operators
// Private Member Operators
//- Increment the ref-count for a managed pointer
inline void operator++();
public:
typedef T Type;
// STL type definitions
//- Type of object being managed or referenced
typedef T element_type;
//- Pointer to type of object being managed or referenced
typedef T* pointer;
//- Reference counter class
typedef Foam::refCount refCount;
// Factory Methods
//- Construct tmp of T with forwarding arguments
// \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>
inline static tmp<T> New(Args&&... args);
//- Construct tmp from derived type with forwarding arguments
// \param args list of arguments with which an instance of U
// will be constructed.
//
// \note Similar to New but for derived types
template<class U, class... Args>
inline static tmp<T> NewFrom(Args&&... args);
// Constructors
//- Null pointer construct
inline tmp();
//- Construct with no managed pointer.
inline constexpr tmp() noexcept;
//- Store object pointer
//- Construct with no managed pointer.
inline constexpr tmp(std::nullptr_t) noexcept;
//- Construct, taking ownership of the pointer.
inline explicit tmp(T* p);
//- Store object const reference
inline tmp(const T& t);
//- Construct for a const reference to an object.
inline tmp(const T& obj) noexcept;
//- Construct copy and increment reference count
//- Move construct, transferring ownership.
// Does not affect ref-count
inline tmp(tmp<T>&& t) noexcept;
//- Move construct, transferring ownership.
// Does not affect ref-count
// \note Non-standard definition - should be non-const
inline tmp(const tmp<T>&& t) noexcept;
//- Copy construct, incrementing ref-count of managed pointer.
// \note Non-standard definition - should be non-const
inline tmp(const tmp<T>& t);
//- Construct copy moving content, does not increment reference count
inline tmp(const tmp<T>&& t);
//- Construct copy transferring content of temporary if required
inline tmp(const tmp<T>& t, bool allowTransfer);
//- Copy construct. Optionally reusing ref-counted pointer.
inline tmp(const tmp<T>& t, bool reuse);
//- Destructor: deletes temporary object when the reference count is 0
//- Destructor: deletes managed pointer when the ref-count is 0
inline ~tmp();
// Member Functions
// Access
// Query
//- Return true if this is really a temporary object
inline bool isTmp() const;
//- True if this is a managed pointer (not a const reference)
inline bool isTmp() const;
//- Return true if this temporary object empty,
// ie, a temporary without allocation
inline bool empty() const;
//- True if this is a non-null managed pointer
inline bool empty() const;
//- Is this temporary object valid,
// ie, it is a reference or a temporary that has been allocated
inline bool valid() const;
//- True if this is a non-null managed pointer,
//- or is a const object reference
inline bool valid() const;
//- Return the type name of the tmp
// constructed from the type name of T
inline word typeName() const;
//- True if this is a non-null managed pointer with a unique ref-count
inline bool movable() const;
//- Return type-name of the tmp, constructed from type-name of T
inline word typeName() const;
// Edit
// Access
//- Return tmp pointer for reuse.
// Returns a clone if the object is not a temporary
inline T* ptr() const;
//- Return the const object reference or a const reference to the
//- contents of a non-null managed pointer.
// Fatal for a null managed pointer
inline const T& cref() const;
//- Return non-const reference. Fatal if the object is const.
inline T& ref() const;
//- Return non-const reference to the contents of a non-null
//- managed pointer.
// Fatal for a null managed pointer or if the object is const.
inline T& ref() const;
//- If object pointer points to valid object:
//- delete object and set pointer to nullptr
inline void clear() const;
//- Non-const dereference, even if the object is const.
// This is similar to ref(), but applies a const_cast to access
// const objects.
// Fatal for a null managed pointer.
inline T& constCast() const;
// Edit
//- Return managed pointer for reuse, or clone() the const object
//- reference.
inline T* ptr() const;
//- If object pointer points to valid object:
//- delete object and set pointer to nullptr
inline void clear() const;
//- Release ownership of managed temporary object.
// After this call no object is managed.
inline void reset();
//- Delete managed temporary object and set to new given pointer
inline void reset(T* p);
//- Swaps the managed object with other tmp.
inline void swap(tmp<T>& other) noexcept;
// Member operators
//- Const dereference operator
//- Return const reference to the object.
// Identical to cref() method.
inline const T& operator()() const;
//- Const cast to the underlying type reference
//- Cast to underlying data type, using the cref() method.
inline operator const T&() const;
//- Return object pointer
inline T* operator->();
//- Return const object pointer
//- Dereferences (const) pointer to the managed object.
// Fatal for a null managed pointer.
inline const T* operator->() const;
//- Assignment to pointer changing this tmp to a temporary T
//- Dereferences (non-const) pointer to the managed object.
// Fatal for a null managed pointer or if the object is const.
inline T* operator->();
//- Take ownership of the pointer.
// Fatal for a null pointer, or when the pointer is non-unique.
inline void operator=(T* p);
//- Assignment transferring the temporary T to this tmp
//- Transfer ownership of the managed pointer.
// Fatal for a null managed pointer or if the object is const.
inline void operator=(const tmp<T>& t);
// Housekeeping
//- Disallow assignment from literal nullptr.
// Consistent with run-time check for nullptr on assignment.
void operator=(std::nullptr_t) = delete;
};
// Global Functions
//- Specializes the Swap algorithm for tmp.
// Swaps the pointers and types of lhs and rhs. Calls \c lhs.swap(rhs)
template<class T>
void Swap(tmp<T>& lhs, tmp<T>& rhs)
{
lhs.swap(rhs);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -43,13 +43,39 @@ inline void Foam::tmp<T>::operator++()
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class T>
template<class... Args>
inline Foam::tmp<T> Foam::tmp<T>::New(Args&&... args)
{
return tmp<T>(new T(std::forward<Args>(args)...));
}
template<class T>
template<class U, class... Args>
inline Foam::tmp<T> Foam::tmp<T>::NewFrom(Args&&... args)
{
return tmp<T>(new U(std::forward<Args>(args)...));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T>
inline Foam::tmp<T>::tmp()
inline constexpr Foam::tmp<T>::tmp() noexcept
:
ptr_(nullptr),
type_(TMP)
type_(PTR)
{}
template<class T>
inline constexpr Foam::tmp<T>::tmp(std::nullptr_t) noexcept
:
ptr_(nullptr),
type_(PTR)
{}
@ -57,7 +83,7 @@ template<class T>
inline Foam::tmp<T>::tmp(T* p)
:
ptr_(p),
type_(TMP)
type_(PTR)
{
if (p && !p->unique())
{
@ -70,13 +96,35 @@ inline Foam::tmp<T>::tmp(T* p)
template<class T>
inline Foam::tmp<T>::tmp(const T& t)
inline Foam::tmp<T>::tmp(const T& obj) noexcept
:
ptr_(const_cast<T*>(&t)),
type_(CONST_REF)
ptr_(const_cast<T*>(&obj)),
type_(CREF)
{}
template<class T>
inline Foam::tmp<T>::tmp(tmp<T>&& t) noexcept
:
ptr_(t.ptr_),
type_(t.type_)
{
t.ptr_ = nullptr;
t.type_ = PTR;
}
template<class T>
inline Foam::tmp<T>::tmp(const tmp<T>&& t) noexcept
:
ptr_(t.ptr_),
type_(t.type_)
{
t.ptr_ = nullptr;
t.type_ = PTR;
}
template<class T>
inline Foam::tmp<T>::tmp(const tmp<T>& t)
:
@ -100,20 +148,7 @@ inline Foam::tmp<T>::tmp(const tmp<T>& t)
template<class T>
inline Foam::tmp<T>::tmp(const tmp<T>&& t)
:
ptr_(t.ptr_),
type_(t.type_)
{
if (isTmp())
{
t.ptr_ = nullptr;
}
}
template<class T>
inline Foam::tmp<T>::tmp(const tmp<T>& t, bool allowTransfer)
inline Foam::tmp<T>::tmp(const tmp<T>& t, bool reuse)
:
ptr_(t.ptr_),
type_(t.type_)
@ -122,9 +157,9 @@ inline Foam::tmp<T>::tmp(const tmp<T>& t, bool allowTransfer)
{
if (ptr_)
{
if (allowTransfer)
if (reuse)
{
t.ptr_ = nullptr;
t.ptr_ = nullptr; // t.type_ already set as PTR
}
else
{
@ -153,21 +188,28 @@ inline Foam::tmp<T>::~tmp()
template<class T>
inline bool Foam::tmp<T>::isTmp() const
{
return type_ == TMP;
return type_ == PTR;
}
template<class T>
inline bool Foam::tmp<T>::empty() const
{
return (isTmp() && !ptr_);
return (!ptr_ && isTmp());
}
template<class T>
inline bool Foam::tmp<T>::valid() const
{
return (!isTmp() || (isTmp() && ptr_));
return (ptr_ || type_ == CREF);
}
template<class T>
inline bool Foam::tmp<T>::movable() const
{
return (type_ == PTR && ptr_ && ptr_->unique());
}
@ -179,7 +221,7 @@ inline Foam::word Foam::tmp<T>::typeName() const
template<class T>
inline T* Foam::tmp<T>::ptr() const
inline const T& Foam::tmp<T>::cref() const
{
if (isTmp())
{
@ -189,22 +231,9 @@ inline T* Foam::tmp<T>::ptr() const
<< typeName() << " deallocated"
<< abort(FatalError);
}
if (!ptr_->unique())
{
FatalErrorInFunction
<< "Attempt to acquire pointer to object referred to"
<< " by multiple temporaries of type " << typeName()
<< abort(FatalError);
}
T* ptr = ptr_;
ptr_ = nullptr;
return ptr;
}
return ptr_->clone().ptr();
return *ptr_; // const reference
}
@ -223,12 +252,55 @@ inline T& Foam::tmp<T>::ref() const
else
{
FatalErrorInFunction
<< "Attempt to acquire non-const reference to const object"
<< " from a " << typeName()
<< "Attempted non-const reference to const object from a "
<< typeName()
<< abort(FatalError);
}
return *ptr_;
return *ptr_; // non-const reference
}
template<class T>
inline T& Foam::tmp<T>::constCast() const
{
if (isTmp() && !ptr_)
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
return const_cast<T&>(*ptr_);
}
template<class T>
inline T* Foam::tmp<T>::ptr() const
{
if (isTmp())
{
if (!ptr_)
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
else if (!ptr_->unique())
{
FatalErrorInFunction
<< "Attempt to acquire pointer to object referred to"
<< " by multiple temporaries of type " << typeName()
<< abort(FatalError);
}
T* ptr = ptr_;
ptr_ = nullptr;
return ptr;
}
return ptr_->clone().ptr();
}
@ -240,41 +312,75 @@ inline void Foam::tmp<T>::clear() const
if (ptr_->unique())
{
delete ptr_;
ptr_ = nullptr;
}
else
{
ptr_->operator--();
ptr_ = nullptr;
}
ptr_ = nullptr;
}
}
template<class T>
inline void Foam::tmp<T>::reset()
{
clear();
ptr_ = nullptr;
type_ = PTR;
}
template<class T>
inline void Foam::tmp<T>::reset(T* p)
{
clear();
ptr_ = p;
type_ = PTR;
}
template<class T>
inline void Foam::tmp<T>::swap(tmp<T>& other) noexcept
{
// Copy/assign for pointer types
T* p = ptr_;
ptr_ = other.ptr_;
other.ptr_ = p;
refType t = type_;
type_ = other.type_;
other.type_ = t;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T>
inline const T& Foam::tmp<T>::operator()() const
{
if (isTmp())
{
if (!ptr_)
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
}
// Return const reference
return *ptr_;
return cref();
}
template<class T>
inline Foam::tmp<T>::operator const T&() const
{
return operator()();
return cref();
}
template<class T>
inline const T* Foam::tmp<T>::operator->() const
{
if (!ptr_ && isTmp())
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
return ptr_;
}
@ -301,20 +407,6 @@ inline T* Foam::tmp<T>::operator->()
}
template<class T>
inline const T* Foam::tmp<T>::operator->() const
{
if (isTmp() && !ptr_)
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
return ptr_;
}
template<class T>
inline void Foam::tmp<T>::operator=(T* p)
{
@ -326,8 +418,7 @@ inline void Foam::tmp<T>::operator=(T* p)
<< "Attempted copy of a deallocated " << typeName()
<< abort(FatalError);
}
if (p && !p->unique())
else if (!p->unique())
{
FatalErrorInFunction
<< "Attempted assignment of a " << typeName()
@ -336,7 +427,7 @@ inline void Foam::tmp<T>::operator=(T* p)
}
ptr_ = p;
type_ = TMP;
type_ = PTR;
}
@ -347,17 +438,16 @@ inline void Foam::tmp<T>::operator=(const tmp<T>& t)
if (t.isTmp())
{
type_ = TMP;
ptr_ = t.ptr_;
type_ = PTR;
t.ptr_ = nullptr;
if (!t.ptr_)
if (!ptr_)
{
FatalErrorInFunction
<< "Attempted assignment to a deallocated " << typeName()
<< abort(FatalError);
}
ptr_ = t.ptr_;
t.ptr_ = nullptr;
}
else
{

View File

@ -0,0 +1,214 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 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/>.
Class
Foam::tmpNrc
Description
A class for managing temporary objects without reference counting.
SourceFiles
tmpNrcI.H
See also
Foam::autoPtr
\*---------------------------------------------------------------------------*/
#ifndef tmpNrc_H
#define tmpNrc_H
#include "refCount.H"
#include "word.H"
#include <utility>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class tmpNrc Declaration
\*---------------------------------------------------------------------------*/
template<class T>
class tmpNrc
{
// Private data
//- Object types
enum refType
{
PTR, //!< Managing a pointer (not ref-counted)
CREF //!< Using a const-reference to an object
};
//- The managed pointer or the address of const-reference object
mutable T* ptr_;
//- The type (managed pointer | const-reference object)
refType type_;
public:
// STL type definitions
//- Type of object being managed
typedef T element_type;
//- Pointer to type of object being managed
typedef T* pointer;
//- Null reference counter class
typedef Foam::refCount::zero refCount;
// Constructors
//- Construct with no managed pointer.
inline constexpr tmpNrc() noexcept;
//- Construct with no managed pointer.
inline constexpr tmpNrc(std::nullptr_t) noexcept;
//- Construct, taking ownership of the pointer.
inline explicit tmpNrc(T* p) noexcept;
//- Construct for a const reference to an object.
inline tmpNrc(const T& obj) noexcept;
//- Copy construct
inline tmpNrc(const tmpNrc<T>& t);
//- Construct copy, transferring content of temporary if required
inline tmpNrc(const tmpNrc<T>& t, bool reuse);
//- Destructor: deletes managed pointer
inline ~tmpNrc();
// Member Functions
// Query
//- True if this is a managed pointer (not a const reference)
inline bool isTmp() const;
//- True if this is a non-null managed pointer
inline bool empty() const;
//- True if this is a non-null managed pointer,
//- or is a const object reference
inline bool valid() const;
//- True if this is a non-null managed pointer with a unique ref-count
inline bool movable() const;
//- Return type-name of the tmp, constructed from type-name of T
inline word typeName() const;
// Access
//- Return the const object reference or a const reference to the
//- contents of a non-null managed pointer.
// Fatal for a null managed pointer
inline const T& cref() const;
//- Return non-const reference to the contents of a non-null
//- managed pointer.
// Fatal for a null managed pointer or if the object is const.
inline T& ref() const;
//- Non-const dereference, even if the object is const.
// This is similar to ref(), but applies a const_cast to access
// const objects.
// Fatal for a null managed pointer.
inline T& constCast() const;
// Edit
//- Return managed pointer for reuse, or clone() the const object
//- reference.
inline T* ptr() const;
//- If object pointer points to valid object:
//- delete object and set pointer to nullptr
inline void clear() const;
// Member operators
//- Return const reference to the object.
// Identical to cref() method.
inline const T& operator()() const;
//- Cast to underlying data type, using the cref() method.
inline operator const T&() const;
//- Dereferences (const) pointer to the managed object.
// Fatal for a null managed pointer.
inline const T* operator->() const;
//- Dereferences (non-const) pointer to the managed object.
// Fatal for a null managed pointer or if the object is const.
inline T* operator->();
//- Take ownership of the pointer.
// Fatal for a null pointer, or when the pointer is non-unique.
inline void operator=(T* p);
//- Transfer ownership of the managed pointer.
// Fatal for a null managed pointer or if the object is const.
inline void operator=(const tmpNrc<T>& t);
};
// Global Functions
//- Specializes the Swap algorithm for tmp.
// Swaps the pointers and types of lhs and rhs. Calls \c lhs.swap(rhs)
template<class T>
void Swap(tmpNrc<T>& lhs, tmpNrc<T>& rhs)
{
lhs.swap(rhs);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "tmpNrcI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,32 +29,48 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T>
inline Foam::tmpNrc<T>::tmpNrc(T* tPtr)
inline constexpr Foam::tmpNrc<T>::tmpNrc() noexcept
:
type_(TMP),
ptr_(tPtr)
ptr_(nullptr),
type_(PTR)
{}
template<class T>
inline Foam::tmpNrc<T>::tmpNrc(const T& tRef)
inline constexpr Foam::tmpNrc<T>::tmpNrc(std::nullptr_t) noexcept
:
type_(CONST_REF),
ptr_(const_cast<T*>(&tRef))
ptr_(nullptr),
type_(PTR)
{}
template<class T>
inline Foam::tmpNrc<T>::tmpNrc(T* p) noexcept
:
ptr_(p),
type_(PTR)
{}
template<class T>
inline Foam::tmpNrc<T>::tmpNrc(const T& obj) noexcept
:
ptr_(const_cast<T*>(&obj)),
type_(CREF)
{}
template<class T>
inline Foam::tmpNrc<T>::tmpNrc(const tmpNrc<T>& t)
:
type_(t.type_),
ptr_(t.ptr_)
ptr_(t.ptr_),
type_(t.type_)
{
if (isTmp())
{
if (ptr_)
{
t.type_ = CONST_REF;
t.type_ = CREF;
}
else
{
@ -67,22 +83,22 @@ inline Foam::tmpNrc<T>::tmpNrc(const tmpNrc<T>& t)
template<class T>
inline Foam::tmpNrc<T>::tmpNrc(const tmpNrc<T>& t, bool allowTransfer)
inline Foam::tmpNrc<T>::tmpNrc(const tmpNrc<T>& t, bool reuse)
:
type_(t.type_),
ptr_(t.ptr_)
ptr_(t.ptr_),
type_(t.type_)
{
if (isTmp())
{
if (ptr_)
{
if (allowTransfer)
if (reuse)
{
t.ptr_ = nullptr;
t.ptr_ = nullptr; // t.type_ already set as PTR
}
else
{
t.type_ = CONST_REF;
t.type_ = CREF;
}
}
else
@ -107,21 +123,28 @@ inline Foam::tmpNrc<T>::~tmpNrc()
template<class T>
inline bool Foam::tmpNrc<T>::isTmp() const
{
return type_ == TMP;
return type_ == PTR;
}
template<class T>
inline bool Foam::tmpNrc<T>::empty() const
{
return (isTmp() && !ptr_);
return (!ptr_ && isTmp());
}
template<class T>
inline bool Foam::tmpNrc<T>::valid() const
{
return (!isTmp() || (isTmp() && ptr_));
return (ptr_ || type_ == CREF);
}
template<class T>
inline bool Foam::tmpNrc<T>::movable() const
{
return (type_ == PTR && ptr_);
}
@ -133,7 +156,24 @@ inline Foam::word Foam::tmpNrc<T>::typeName() const
template<class T>
inline T& Foam::tmpNrc<T>::ref()
inline const T& Foam::tmpNrc<T>::cref() const
{
if (isTmp())
{
if (!ptr_)
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
}
return *ptr_; // const reference
}
template<class T>
inline T& Foam::tmpNrc<T>::ref() const
{
if (isTmp())
{
@ -147,12 +187,26 @@ inline T& Foam::tmpNrc<T>::ref()
else
{
FatalErrorInFunction
<< "Attempt to acquire non-const reference to const object"
<< " from a " << typeName()
<< "Attempted non-const reference to const object from a "
<< typeName()
<< abort(FatalError);
}
return *ptr_;
return *ptr_; // non-const reference
}
template<class T>
inline T& Foam::tmpNrc<T>::constCast() const
{
if (isTmp() && !ptr_)
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
return const_cast<T&>(*ptr_);
}
@ -173,10 +227,8 @@ inline T* Foam::tmpNrc<T>::ptr() const
return ptr;
}
else
{
return ptr_->clone().ptr();
}
return ptr_->clone().ptr();
}
@ -191,30 +243,47 @@ inline void Foam::tmpNrc<T>::clear() const
}
template<class T>
inline void Foam::tmpNrc<T>::swap(tmpNrc<T>& other) noexcept
{
// Copy/assign for pointer types
T* p = ptr_;
ptr_ = other.ptr_;
other.ptr_ = p;
refType t = type_;
type_ = other.type_;
other.type_ = t;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T>
inline const T& Foam::tmpNrc<T>::operator()() const
{
if (isTmp())
{
if (!ptr_)
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
}
// Return const reference
return *ptr_;
return cref();
}
template<class T>
inline Foam::tmpNrc<T>::operator const T&() const
{
return operator()();
return cref();
}
template<class T>
inline const T* Foam::tmpNrc<T>::operator->() const
{
if (!ptr_ && isTmp())
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
return ptr_;
}
@ -242,33 +311,19 @@ inline T* Foam::tmpNrc<T>::operator->()
template<class T>
inline const T* Foam::tmpNrc<T>::operator->() const
{
if (isTmp() && !ptr_)
{
FatalErrorInFunction
<< typeName() << " deallocated"
<< abort(FatalError);
}
return ptr_;
}
template<class T>
inline void Foam::tmpNrc<T>::operator=(T* tPtr)
inline void Foam::tmpNrc<T>::operator=(T* p)
{
clear();
if (!tPtr)
if (!p)
{
FatalErrorInFunction
<< "Attempted copy of a deallocated " << typeName()
<< abort(FatalError);
}
type_ = TMP;
ptr_ = tPtr;
ptr_ = p;
type_ = PTR;
}
@ -279,17 +334,16 @@ inline void Foam::tmpNrc<T>::operator=(const tmpNrc<T>& t)
if (t.isTmp())
{
type_ = TMP;
ptr_ = t.ptr_;
type_ = PTR;
t.ptr_ = nullptr;
if (!t.ptr_)
if (!ptr_)
{
FatalErrorInFunction
<< "Attempted assignment to a deallocated " << typeName()
<< abort(FatalError);
}
ptr_ = t.ptr_;
t.ptr_ = nullptr;
}
else
{

View File

@ -1,171 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 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/>.
Class
Foam::tmpNrc
Description
A class for managing temporary objects without reference counting.
SourceFiles
tmpNrcI.H
See also
Foam::autoPtr
\*---------------------------------------------------------------------------*/
#ifndef tmpNrc_H
#define tmpNrc_H
#include "word.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class tmpNrc Declaration
\*---------------------------------------------------------------------------*/
template<class T>
class tmpNrc
{
// Private data
//- Object types
enum type
{
TMP,
CONST_REF
};
//- Type of object
mutable type type_;
//- Pointer to object
mutable T* ptr_;
public:
// Null reference counter class
class refCount
{
public:
refCount()
{}
};
// Constructors
//- Store object pointer
inline explicit tmpNrc(T* tPtr = nullptr);
//- Store object const reference
inline tmpNrc(const T& tRef);
//- Construct copy and increment reference count
inline tmpNrc(const tmpNrc<T>& t);
//- Construct copy transferring content of temporary if required
inline tmpNrc(const tmpNrc<T>& t, bool allowTransfer);
//- Destructor: deletes temporary object when the reference count is 0
inline ~tmpNrc();
// Member Functions
// Access
//- Return true if this is really a temporary object
inline bool isTmp() const;
//- Return true if this temporary object empty,
// ie, a temporary without allocation
inline bool empty() const;
//- Is this temporary object valid,
// ie, it is a reference or a temporary that has been allocated
inline bool valid() const;
//- Return the type name of the tmpNrc
// constructed from the type name of T
inline word typeName() const;
// Edit
//- Return non-const reference or generate a fatal error
// if the object is const.
inline T& ref();
//- Return tmpNrc pointer for reuse.
// Returns a clone if the object is not a temporary
inline T* ptr() const;
//- If object pointer points to valid object:
// delete object and set pointer to nullptr
inline void clear() const;
// Member operators
//- Const dereference operator
inline const T& operator()() const;
//- Const cast to the underlying type reference
inline operator const T&() const;
//- Return object pointer
inline T* operator->();
//- Return const object pointer
inline const T* operator->() const;
//- Assignment to pointer changing this tmpNrc to a temporary T
inline void operator=(T* tPtr);
//- Assignment transferring the temporary T to this tmpNrc
inline void operator=(const tmpNrc<T>& t);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "tmpNrcI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -79,8 +79,7 @@ Foam::tmp<Foam::Field<Type>> Foam::Function1<Type>::value
) const
{
NotImplemented;
return tmp<Foam::Field<Type>>(nullptr);
return tmp<Field<Type>>();
}
@ -101,8 +100,7 @@ Foam::tmp<Foam::Field<Type>> Foam::Function1<Type>::integrate
) const
{
NotImplemented;
return tmp<Foam::Field<Type>>(nullptr);
return tmp<Field<Type>>();
}

View File

@ -417,15 +417,13 @@ public:
vf, model.muEff()/model.rho(), model.U(), delta
);
}
else
{
FatalErrorInFunction
<< "Scheme requires a turbulence model to be present. "
<< "Unable to retrieve turbulence model from the mesh "
<< "database" << exit(FatalError);
return tmp<surfaceScalarField>(nullptr);
}
FatalErrorInFunction
<< "Scheme requires a turbulence model to be present. "
<< "Unable to retrieve turbulence model from the mesh "
<< "database" << exit(FatalError);
return tmp<surfaceScalarField>();
}
@ -501,13 +499,8 @@ public:
{
return (bf*tScheme2_().correction(vf));
}
else
{
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
nullptr
);
}
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>();
}
};

View File

@ -79,7 +79,7 @@ protected:
template<class GeoFieldType>
void correctBoundaryConditions(const tmp<GeoFieldType>& tgf) const
{
const_cast<GeoFieldType&>(tgf()).correctBoundaryConditions();
tgf.constCast().correctBoundaryConditions();
}

View File

@ -148,7 +148,7 @@ public:
virtual tmp<GeometricField<Type, faePatchField, edgeMesh>>
correction(const GeometricField<Type, faPatchField, areaMesh>&) const
{
return tmp<GeometricField<Type, faePatchField, edgeMesh>>(nullptr);
return tmp<GeometricField<Type, faePatchField, edgeMesh>>();
}
//- Return the lnGrad of the given cell field

View File

@ -189,7 +189,7 @@ public:
virtual tmp<GeometricField<Type, faePatchField, edgeMesh>>
correction(const GeometricField<Type, faPatchField, areaMesh>&) const
{
return tmp<GeometricField<Type, faePatchField, edgeMesh>>(nullptr);
return tmp<GeometricField<Type, faePatchField, edgeMesh>>();
}
//- Return the face-interpolate of the given cell field

View File

@ -135,14 +135,12 @@ tmp<surfaceScalarField> CoEulerDdtScheme<Type>::CofrDeltaT() const
return max(Co/maxCo_, scalar(1))/deltaT;
}
else
{
FatalErrorInFunction
<< "Incorrect dimensions of phi: " << phi.dimensions()
<< abort(FatalError);
return tmp<surfaceScalarField>(nullptr);
}
FatalErrorInFunction
<< "Incorrect dimensions of phi: " << phi.dimensions()
<< abort(FatalError);
return tmp<surfaceScalarField>();
}

View File

@ -56,13 +56,8 @@ Foam::tmp<Foam::labelField> Foam::regionCoupledFvPatch::internalFieldTransfer
{
return neighbFvPatch().patchInternalField(iF);
}
else
{
return tmp<labelField>(new labelField(iF.size(), 0));
}
return tmp<labelField>(nullptr);
return tmp<labelField>(new labelField(iF.size(), 0));
}

View File

@ -58,12 +58,8 @@ internalFieldTransfer
{
return neighbFvPatch().patchInternalField(iF);
}
else
{
return tmp<labelField>(new labelField(iF.size(), 0));
}
return tmp<labelField>(nullptr);
return tmp<labelField>(new labelField(iF.size(), 0));
}
// ************************************************************************* //

View File

@ -62,14 +62,12 @@ Foam::heatTransferCoeffModels::ReynoldsAnalogy::rho(const label patchi) const
mesh_.lookupObject<volScalarField>(rhoName_);
return rho.boundaryField()[patchi];
}
else
{
FatalErrorInFunction
<< "Unable to set rho for patch " << patchi
<< exit(FatalError);
}
return tmp<Field<scalar>>(nullptr);
FatalErrorInFunction
<< "Unable to set rho for patch " << patchi
<< exit(FatalError);
return tmp<Field<scalar>>();
}
@ -91,14 +89,12 @@ Foam::heatTransferCoeffModels::ReynoldsAnalogy::Cp(const label patchi) const
return thermo.Cp(pp, Tp, patchi);
}
else
{
FatalErrorInFunction
<< "Unable to set Cp for patch " << patchi
<< exit(FatalError);
}
return tmp<Field<scalar>>(nullptr);
FatalErrorInFunction
<< "Unable to set Cp for patch " << patchi
<< exit(FatalError);
return tmp<Field<scalar>>();
}

View File

@ -119,7 +119,7 @@ Foam::fv::solidificationMeltingSource::Cp() const
}
}
return tmp<volScalarField>(nullptr);
return tmp<volScalarField>();
}

View File

@ -109,8 +109,7 @@ Foam::ParticleStressModels::Lun::dTaudTheta
) const
{
NotImplemented;
return tmp<Field<scalar>>(nullptr);
return tmp<Field<scalar>>();
}

View File

@ -47,15 +47,13 @@ Foam::DispersionRASModel<CloudType>::kModel() const
obr.lookupObject<turbulenceModel>(turbName);
return model.k();
}
else
{
FatalErrorInFunction
<< "Turbulence model not found in mesh database" << nl
<< "Database objects include: " << obr.sortedToc()
<< abort(FatalError);
return tmp<volScalarField>(nullptr);
}
FatalErrorInFunction
<< "Turbulence model not found in mesh database" << nl
<< "Database objects include: " << obr.sortedToc()
<< abort(FatalError);
return tmp<volScalarField>();
}
@ -77,15 +75,13 @@ Foam::DispersionRASModel<CloudType>::epsilonModel() const
obr.lookupObject<turbulenceModel>(turbName);
return model.epsilon();
}
else
{
FatalErrorInFunction
<< "Turbulence model not found in mesh database" << nl
<< "Database objects include: " << obr.sortedToc()
<< abort(FatalError);
return tmp<volScalarField>(nullptr);
}
FatalErrorInFunction
<< "Turbulence model not found in mesh database" << nl
<< "Database objects include: " << obr.sortedToc()
<< abort(FatalError);
return tmp<volScalarField>();
}

View File

@ -70,15 +70,13 @@ Foam::BrownianMotionForce<CloudType>::kModel() const
obr.lookupObject<turbulenceModel>(turbName);
return model.k();
}
else
{
FatalErrorInFunction
<< "Turbulence model not found in mesh database" << nl
<< "Database objects include: " << obr.sortedToc()
<< abort(FatalError);
return tmp<volScalarField>(nullptr);
}
FatalErrorInFunction
<< "Turbulence model not found in mesh database" << nl
<< "Database objects include: " << obr.sortedToc()
<< abort(FatalError);
return tmp<volScalarField>();
}

View File

@ -70,7 +70,7 @@ Foam::tmp<Foam::vectorField> Foam::EulerCoordinateRotation::transform
) const
{
NotImplemented;
return tmp<vectorField>(nullptr);
return tmp<vectorField>();
}
@ -80,7 +80,7 @@ Foam::tmp<Foam::vectorField> Foam::EulerCoordinateRotation::invTransform
) const
{
NotImplemented;
return tmp<vectorField>(nullptr);
return tmp<vectorField>();
}
@ -97,7 +97,7 @@ Foam::tmp<Foam::tensorField> Foam::EulerCoordinateRotation::transformTensor
) const
{
NotImplemented;
return tmp<tensorField>(nullptr);
return tmp<tensorField>();
}
@ -117,7 +117,7 @@ Foam::tmp<Foam::tensorField> Foam::EulerCoordinateRotation::transformTensor
) const
{
NotImplemented;
return tmp<tensorField>(nullptr);
return tmp<tensorField>();
}

View File

@ -71,7 +71,7 @@ Foam::tmp<Foam::vectorField> Foam::STARCDCoordinateRotation::transform
) const
{
NotImplemented;
return tmp<vectorField>(nullptr);
return tmp<vectorField>();
}
@ -81,7 +81,7 @@ Foam::tmp<Foam::vectorField> Foam::STARCDCoordinateRotation::invTransform
) const
{
NotImplemented;
return tmp<vectorField>(nullptr);
return tmp<vectorField>();
}
@ -98,7 +98,7 @@ Foam::tmp<Foam::tensorField> Foam::STARCDCoordinateRotation::transformTensor
) const
{
NotImplemented;
return tmp<tensorField>(nullptr);
return tmp<tensorField>();
}
@ -118,7 +118,7 @@ Foam::tmp<Foam::tensorField> Foam::STARCDCoordinateRotation::transformTensor
) const
{
NotImplemented;
return tmp<tensorField>(nullptr);
return tmp<tensorField>();
}

View File

@ -245,7 +245,7 @@ Foam::tmp<Foam::tensorField> Foam::axesRotation::transformTensor
) const
{
NotImplemented;
return tmp<tensorField>(nullptr);
return tmp<tensorField>();
}
@ -265,7 +265,7 @@ Foam::tmp<Foam::tensorField> Foam::axesRotation::transformTensor
) const
{
NotImplemented;
return tmp<tensorField>(nullptr);
return tmp<tensorField>();
}

View File

@ -137,7 +137,7 @@ Foam::tmp<Foam::scalarField> Foam::sampledSurface::sample
) const
{
NotImplemented;
return tmp<scalarField>(nullptr);
return tmp<scalarField>();
}
@ -147,7 +147,7 @@ Foam::tmp<Foam::vectorField> Foam::sampledSurface::sample
) const
{
NotImplemented;
return tmp<vectorField>(nullptr);
return tmp<vectorField>();
}
@ -157,7 +157,7 @@ Foam::tmp<Foam::sphericalTensorField> Foam::sampledSurface::sample
) const
{
NotImplemented;
return tmp<sphericalTensorField>(nullptr);
return tmp<sphericalTensorField>();
}
@ -167,7 +167,7 @@ Foam::tmp<Foam::symmTensorField> Foam::sampledSurface::sample
) const
{
NotImplemented;
return tmp<symmTensorField>(nullptr);
return tmp<symmTensorField>();
}
@ -177,7 +177,7 @@ Foam::tmp<Foam::tensorField> Foam::sampledSurface::sample
) const
{
NotImplemented;
return tmp<tensorField>(nullptr);
return tmp<tensorField>();
}

View File

@ -66,7 +66,7 @@ void Foam::radiation::noSoot::correct()
const Foam::volScalarField& Foam::radiation::noSoot::soot() const
{
NotImplemented;
return tmp<volScalarField>(nullptr);
return tmp<volScalarField>();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -69,7 +69,7 @@ Foam::basicSolidChemistryModel::RR(const label i)
return dynamic_cast<volScalarField::Internal&>
(
const_cast<volScalarField::Internal& >
const_cast<volScalarField::Internal&>
(
volScalarField::Internal::null()
)
@ -88,7 +88,7 @@ Foam::basicSolidChemistryModel::calculateRR
return dynamic_cast<tmp<volScalarField::Internal>&>
(
const_cast<volScalarField::Internal& >
const_cast<volScalarField::Internal&>
(
volScalarField::Internal::null()
)

View File

@ -106,11 +106,11 @@ void Foam::waveAlphaFvPatchScalarField::updateCoeffs()
)
);
waveModel& model = const_cast<waveModel&>(tmodel());
waveModel& model = tmodel.constCast();
model.correct(db().time().value());
operator == (model.alpha());
operator==(model.alpha());
fixedValueFvPatchField<scalar>::updateCoeffs();
}

View File

@ -106,11 +106,11 @@ void Foam::waveVelocityFvPatchVectorField::updateCoeffs()
)
);
waveModel& model = const_cast<waveModel&>(tmodel());
waveModel& model = tmodel.constCast();
model.correct(db().time().value());
operator == (model.U());
operator==(model.U());
fixedValueFvPatchField<vector>::updateCoeffs();
}