ENH: use refPtr to manage current fileHandler

- for special cases it can simplify sharing of processor communication
  patterns, but no visible change for most code.

- make fileHandler communicator modifiable (mutable), for special
  cases. The changes from 9711b7f1b9 now make this safer to do.

Continue to support legacy global function using an autoPtr:

   autoPtr<fileOperation> Foam::fileHandler(autoPtr<fileOperation>&&);

However, new code using refPtr uses the following static method since
swapping out file handlers is an infrequent operation that should
also stand out a bit more.

    fileOperation::fileHandler(...);
This commit is contained in:
Mark Olesen
2022-12-06 10:47:48 +01:00
parent 19254d0cf2
commit abc60d4d20
6 changed files with 311 additions and 156 deletions

View File

@ -19,6 +19,7 @@ global/etcFiles/etcFiles.C
fileOps = global/fileOperations
$(fileOps)/fileOperation/fileOperation.C
$(fileOps)/fileOperation/fileOperationBroadcast.C
$(fileOps)/fileOperation/fileOperationNew.C
$(fileOps)/fileOperationInitialise/fileOperationInitialise.C
$(fileOps)/uncollatedFileOperation/uncollatedFileOperation.C
$(fileOps)/masterUncollatedFileOperation/masterUncollatedFileOperation.C

View File

@ -166,18 +166,20 @@ void Foam::Time::readDict()
}
controlDict_.watchIndices().clear();
// The new handler, with verbosity
autoPtr<fileOperation> newHandler =
fileOperation::New(fileHandlerName, true);
// The new handler, create with some verbosity
refPtr<fileOperation> newHandler
(
fileOperation::New(fileHandlerName, true)
);
if (TimePaths::distributed() && newHandler)
// Install the new handler
(void) fileOperation::fileHandler(newHandler);
if (TimePaths::distributed())
{
newHandler->distributed(true);
}
// Installing the new handler
Foam::fileHandler(std::move(newHandler));
// Reinstall old watches
fileHandler().addWatches(controlDict_, oldWatched);
}

View File

@ -1231,7 +1231,10 @@ void Foam::argList::parse
handlerType = fileOperation::defaultFileHandler;
}
Foam::fileHandler(fileOperation::New(handlerType, bannerEnabled()));
(void) fileOperation::fileHandler
(
fileOperation::New(handlerType, bannerEnabled())
);
}
@ -1830,7 +1833,7 @@ Foam::argList::~argList()
jobInfo.stop(); // Normal job termination
// Delete file handler to flush any remaining IO
(void)Foam::fileHandler(nullptr);
(void) fileOperation::fileHandler(nullptr);
}

View File

@ -27,7 +27,6 @@ License
\*---------------------------------------------------------------------------*/
#include "fileOperation.H"
#include "uncollatedFileOperation.H"
#include "regIOobject.H"
#include "argList.H"
#include "HashSet.H"
@ -81,8 +80,6 @@ Foam::fileOperation::pathTypeNames_
Foam::word Foam::fileOperation::processorsBaseDir = "processors";
Foam::autoPtr<Foam::fileOperation> Foam::fileOperation::fileHandlerPtr_;
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@ -219,6 +216,7 @@ void sortProcessorDirs(Foam::UList<Foam::fileOperation::dirIndex>& dirs)
} // End anonymous namespace
#endif
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::labelList Foam::fileOperation::ioRanks()
@ -739,54 +737,8 @@ Foam::fileOperation::fileOperation
{}
Foam::autoPtr<Foam::fileOperation>
Foam::fileOperation::New
(
const word& handlerType,
bool verbose
)
{
if (handlerType.empty())
{
if (fileOperation::defaultFileHandler.empty())
{
FatalErrorInFunction
<< "defaultFileHandler name is undefined" << nl
<< abort(FatalError);
}
return fileOperation::New(fileOperation::defaultFileHandler, verbose);
}
DebugInFunction
<< "Constructing fileHandler" << endl;
auto* ctorPtr = wordConstructorTable(handlerType);
if (!ctorPtr)
{
FatalErrorInLookup
(
"fileHandler",
handlerType,
*wordConstructorTablePtr_
) << abort(FatalError);
}
return autoPtr<fileOperation>(ctorPtr(verbose));
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::fileOperation::distributed(bool on) const noexcept
{
bool old(distributed_);
distributed_ = on;
return old;
}
Foam::fileName Foam::fileOperation::objectPath
(
const IOobject& io,
@ -1542,75 +1494,4 @@ Foam::label Foam::fileOperation::detectProcessorPath(const fileName& fName)
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::autoPtr<Foam::fileOperation> Foam::fileOperation::NewUncollated()
{
return autoPtr<fileOperation>
(
new fileOperations::uncollatedFileOperation(false)
);
}
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
const Foam::fileOperation& Foam::fileHandler()
{
if (!fileOperation::fileHandlerPtr_)
{
word handlerType(Foam::getEnv("FOAM_FILEHANDLER"));
if (handlerType.empty())
{
handlerType = fileOperation::defaultFileHandler;
}
fileOperation::fileHandlerPtr_ = fileOperation::New(handlerType, true);
}
return *fileOperation::fileHandlerPtr_;
}
Foam::autoPtr<Foam::fileOperation>
Foam::fileHandler(std::nullptr_t)
{
return autoPtr<fileOperation>(fileOperation::fileHandlerPtr_.release());
}
Foam::autoPtr<Foam::fileOperation>
Foam::fileHandler(autoPtr<fileOperation>&& newHandler)
{
// - do nothing if newHandler is empty. Does not delete current
// - do nothing if newHandler is identical to current handler
// Change ownership as atomic operations
// If newHandler and current handler are actually identical, we
// have a bit problem somewhere else since this means that the pointer
// is managed is done in two places!
// Should flag as a FatalError (in the future), but there may still be
// some place where we would like to fake shared pointers?
// TBD: add a flush() operation on the old handler first,
// instead of waiting for it to be run on destruction?
autoPtr<fileOperation> old;
if
(
newHandler.get() != nullptr
&& newHandler.get() != fileOperation::fileHandlerPtr_.get()
)
{
old.reset(newHandler.release());
old.swap(fileOperation::fileHandlerPtr_);
}
return old;
}
// ************************************************************************* //

View File

@ -43,10 +43,9 @@ Description
#include "ISstream.H"
#include "Ostream.H"
#include "autoPtr.H"
#include "fileMonitor.H"
#include "fileNameList.H"
#include "instantList.H"
#include "fileMonitor.H"
#include "refPtr.H"
#include "Enum.H"
#include "Tuple2.H"
@ -105,13 +104,12 @@ public:
//- identical to UPstream::rangeType
typedef IntRange<int> procRangeType;
protected:
// Protected Data
//- Communicator to use
const label comm_;
mutable label comm_;
//- Distributed roots (parallel run)
mutable bool distributed_;
@ -120,7 +118,7 @@ protected:
mutable HashTable<dirIndexList> procsDirs_;
//- File-change monitor for all registered files
mutable autoPtr<fileMonitor> monitorPtr_;
mutable std::unique_ptr<fileMonitor> monitorPtr_;
// Protected Member Functions
@ -180,11 +178,8 @@ public:
TypeName("fileOperation");
//- Static fileOperation
static autoPtr<fileOperation> fileHandlerPtr_;
//- Static construct the commonly used uncollatedFileOperation
static autoPtr<fileOperation> NewUncollated();
//- The currently active file handler. Avoid accessing directly
static refPtr<fileOperation> fileHandlerPtr_;
// Constructors
@ -229,6 +224,60 @@ public:
virtual ~fileOperation() = default;
// Factory Methods, Singleton-type Functions
//- The commonly used uncollatedFileOperation
static autoPtr<fileOperation> NewUncollated();
//- Return the current file handler.
//- Will create the default file handler if necessary.
static const fileOperation& fileHandler();
//- Delete current file handler.
// \returns the old handler.
// Should have [[nodiscard]], but gcc ignores void casting.
static refPtr<fileOperation> fileHandler(std::nullptr_t);
//- Replace the current file handler.
// The following are considered no-ops:
// - an empty/invalid newHandler does \b not delete, use a literal
// \c nullptr (std::nullptr_t) for that
// - if new handler and current handler are identical (same pointer).
// .
// \returns the old handler (on change), nullptr otherwise
// Should have [[nodiscard]], but gcc ignores void casting.
static refPtr<fileOperation> fileHandler
(
refPtr<fileOperation>& newHandler
);
//- Replace the current file handler.
// The following are considered no-ops:
// - an empty/invalid newHandler does \b not delete, use a literal
// \c nullptr (std::nullptr_t) for that
// - if new handler and current handler are identical (same pointer).
// .
// \returns the old handler (on change), nullptr otherwise
// Should have [[nodiscard]], but gcc ignores void casting.
static refPtr<fileOperation> fileHandler
(
refPtr<fileOperation>&& newHandler
);
//- Replace the current file handler.
// The following are considered no-ops:
// - an empty/invalid newHandler does \b not delete, use a literal
// \c nullptr (std::nullptr_t) for that
// - if new handler and current handler are identical (same pointer).
// .
// \returns the old handler (on change), nullptr otherwise
// Should have [[nodiscard]], but gcc ignores void casting.
static refPtr<fileOperation> fileHandler
(
autoPtr<fileOperation>&& newHandler
);
// Static Functions
//- Sort directory entries according to time value,
@ -248,17 +297,41 @@ public:
// Member Functions
// Characteristics
//- Communicator to use
label comm() const noexcept
{
return comm_;
}
//- Set communicator to use [mutable]. Negative values are a no-op.
// \return old value
label comm(label communicator) const noexcept
{
label old(comm_);
if (communicator >= 0) comm_ = communicator;
return old;
}
//- Distributed roots (parallel run)
bool distributed() const noexcept
{
return distributed_;
}
//- Set distributed roots on/off (mutable)
//- Set distributed roots on/off [mutable]
// \return old value
bool distributed(bool on) const noexcept;
bool distributed(bool on) const noexcept
{
bool old(distributed_);
distributed_ = on;
return old;
}
// Member Functions
// OSSpecific equivalents
//- Make directory
@ -653,23 +726,23 @@ inline Ostream& operator<<(Ostream& os, const fileOperation::pathType b)
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
// Note: defined in fileOperation.C
//- Return the current file handler
//- (will create default file handler if necessary).
//- Forwards to fileOperation::handler()
inline const fileOperation& fileHandler()
{
return fileOperation::fileHandler();
}
//- Return the current file handler.
//- Will create the default file handler if necessary.
const fileOperation& fileHandler();
//- Delete current file handler - forwards to fileOperation::handler()
// Should have [[nodiscard]], but gcc ignores void casting.
inline refPtr<fileOperation> fileHandler(std::nullptr_t)
{
return fileOperation::fileHandler(nullptr);
}
//- Delete current file handler.
// \returns the old handler
autoPtr<fileOperation> fileHandler(std::nullptr_t);
//- Replace the current file handler.
// The following are considered no-ops:
// - an empty/invalid newHandler does \b not delete,
// use fileHandler(std::nullptr_t) - ie, a literal \c nullptr for that
// - if new handler and current handler are identical (same pointer).
// .
// \returns the old handler (on change), nullptr otherwise
//- Replace the current file handler - forwards to fileOperation::handler().
// \note legacy behaviour, so returns autoPtr instead of refPtr!
autoPtr<fileOperation> fileHandler(autoPtr<fileOperation>&& newHandler);

View File

@ -0,0 +1,195 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "fileOperation.H"
#include "uncollatedFileOperation.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
Foam::refPtr<Foam::fileOperation> Foam::fileOperation::fileHandlerPtr_;
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
const Foam::fileOperation& Foam::fileOperation::fileHandler()
{
if (!fileOperation::fileHandlerPtr_)
{
word handlerType(Foam::getEnv("FOAM_FILEHANDLER"));
if (handlerType.empty())
{
handlerType = defaultFileHandler;
}
fileOperation::fileHandlerPtr_ = fileOperation::New(handlerType, true);
}
return *fileOperation::fileHandlerPtr_;
}
Foam::refPtr<Foam::fileOperation>
Foam::fileOperation::fileHandler(std::nullptr_t)
{
return refPtr<fileOperation>(std::move(fileHandlerPtr_));
}
Foam::refPtr<Foam::fileOperation>
Foam::fileOperation::fileHandler(refPtr<fileOperation>& newHandler)
{
// - do nothing if newHandler is empty. Does not delete current
// - do nothing if newHandler is identical to current handler
// Change ownership as atomic operations
// If newHandler and current handler are actually identical, we
// have a bit problem somewhere else since this means that the pointer
// is managed is done in two places!
// Should flag as a FatalError (in the future), but there may still be
// some place where we would like to fake shared pointers?
// TBD: add a flush() operation on the old handler first,
// instead of waiting for it to be run on destruction?
refPtr<fileOperation> old;
if
(
newHandler.get() != nullptr
&& newHandler.get() != fileOperation::fileHandlerPtr_.get()
)
{
old.swap(newHandler);
old.swap(fileOperation::fileHandlerPtr_);
}
return old;
}
Foam::refPtr<Foam::fileOperation>
Foam::fileOperation::fileHandler(autoPtr<fileOperation>&& newHandler)
{
// Same logic as refPtr version
refPtr<fileOperation> old;
if
(
newHandler.get() != nullptr
&& newHandler.get() != fileOperation::fileHandlerPtr_.get()
)
{
old.reset(newHandler.release());
old.swap(fileOperation::fileHandlerPtr_);
}
return old;
}
Foam::refPtr<Foam::fileOperation>
Foam::fileOperation::fileHandler(refPtr<fileOperation>&& newHandler)
{
return fileOperation::fileHandler(newHandler);
}
Foam::autoPtr<Foam::fileOperation> Foam::fileOperation::NewUncollated()
{
return autoPtr<fileOperation>
(
new fileOperations::uncollatedFileOperation(false)
);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::fileOperation>
Foam::fileOperation::New
(
const word& handlerType,
bool verbose
)
{
if (handlerType.empty())
{
if (fileOperation::defaultFileHandler.empty())
{
FatalErrorInFunction
<< "Default file-handler name is undefined" << nl
<< abort(FatalError);
}
return fileOperation::New(fileOperation::defaultFileHandler, verbose);
}
DebugInFunction
<< "Constructing fileHandler" << endl;
auto* ctorPtr = wordConstructorTable(handlerType);
if (!ctorPtr)
{
FatalErrorInLookup
(
"fileHandler",
handlerType,
*wordConstructorTablePtr_
) << abort(FatalError);
}
return autoPtr<fileOperation>(ctorPtr(verbose));
}
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
Foam::autoPtr<Foam::fileOperation>
Foam::fileHandler(autoPtr<fileOperation>&& newHandler)
{
refPtr<fileOperation> oldHandler
(
fileOperation::fileHandler(std::move(newHandler))
);
autoPtr<fileOperation> old;
// Can return as autoPtr if handler was also a pointer (not a reference)
if (oldHandler.is_pointer())
{
old.reset(oldHandler.release());
}
return old;
}
// ************************************************************************* //