mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: more consistent single-ownership when swapping fileHandlers
- make fileHandler deletion mechanism more
transparent by providing a nullptr signature. A nullptr parameter
is already being used in the argList destructor for shutdown, but that
relied on an implicit conversion to autoPtr to trigger things.
- improved handling of file handler replacement.
Previously had a very basic check on old vs new handlers using their
type() values (string comparison!!), which would unfortunately
prevent proper swapping of the contents.
Check the actual pointers instead.
As part of the change, treat any empty autoPtr as no-op instead of as
deletion (which is handled explicitly as nullptr instead).
In addition to making the internal logic simpler, it means that the
current file handler always changes to a valid state without
inadvertently removing everything and falling back to creating a new
default handler (again).
This handling of no-ops also simplifies call code. For example,
<code>
autoPtr<fileHandler> oldHandler;
autoPtr<fileHandler> writeHandler;
word handlerName;
if (arg.readIfPresent("writeHandler", handlerName))
{
writeHandler = fileOperation::New(handlerName);
}
oldHandler = fileHandler(std::move(writeHandler));
... do something
writeHandler = fileHandler(std::move(oldHandler));
</code>
If the "writeHandler" is not specified, each call is a no-op.
If it is specified, the handlers are swapped out each time.
- the management of the fileHandler communicators is now encapsulated
privately (managedComm_) with the final layer being responsible for
cleaning up after itself. This makes delegation/inheritance clearer
and avoids the risk of freeing an MPI communicator twice.
STYLE: uniformFile static check relocated to fileOperation layer
This commit is contained in:
committed by
Andrew Heather
parent
ffeef76d8f
commit
9711b7f1b9
@ -96,11 +96,7 @@ void Foam::masterOFstream::commit()
|
|||||||
filePaths[Pstream::myProcNo()] = pathName_;
|
filePaths[Pstream::myProcNo()] = pathName_;
|
||||||
Pstream::gatherList(filePaths);
|
Pstream::gatherList(filePaths);
|
||||||
|
|
||||||
bool uniform =
|
bool uniform = fileOperation::uniformFile(filePaths);
|
||||||
fileOperations::masterUncollatedFileOperation::uniformFile
|
|
||||||
(
|
|
||||||
filePaths
|
|
||||||
);
|
|
||||||
|
|
||||||
Pstream::broadcast(uniform);
|
Pstream::broadcast(uniform);
|
||||||
|
|
||||||
|
|||||||
@ -1815,7 +1815,7 @@ Foam::argList::~argList()
|
|||||||
jobInfo.stop(); // Normal job termination
|
jobInfo.stop(); // Normal job termination
|
||||||
|
|
||||||
// Delete file handler to flush any remaining IO
|
// Delete file handler to flush any remaining IO
|
||||||
Foam::fileHandler(nullptr);
|
(void)Foam::fileHandler(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -287,7 +287,7 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
|||||||
),
|
),
|
||||||
false
|
false
|
||||||
),
|
),
|
||||||
myComm_(comm_),
|
managedComm_(comm_),
|
||||||
writer_(mag(maxThreadFileBufferSize), comm_),
|
writer_(mag(maxThreadFileBufferSize), comm_),
|
||||||
nProcs_(Pstream::nProcs()),
|
nProcs_(Pstream::nProcs()),
|
||||||
ioRanks_(ioRanks())
|
ioRanks_(ioRanks())
|
||||||
@ -305,7 +305,7 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
masterUncollatedFileOperation(comm, false),
|
masterUncollatedFileOperation(comm, false),
|
||||||
myComm_(-1),
|
managedComm_(-1), // Externally managed
|
||||||
writer_(mag(maxThreadFileBufferSize), comm),
|
writer_(mag(maxThreadFileBufferSize), comm),
|
||||||
nProcs_(Pstream::nProcs()),
|
nProcs_(Pstream::nProcs()),
|
||||||
ioRanks_(ioRanks)
|
ioRanks_(ioRanks)
|
||||||
@ -321,9 +321,9 @@ Foam::fileOperations::collatedFileOperation::~collatedFileOperation()
|
|||||||
// Wait for any outstanding file operations
|
// Wait for any outstanding file operations
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
if (myComm_ != -1 && myComm_ != UPstream::worldComm)
|
if (UPstream::isUserComm(managedComm_))
|
||||||
{
|
{
|
||||||
UPstream::freeCommunicator(myComm_);
|
UPstream::freeCommunicator(managedComm_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -67,6 +67,12 @@ class collatedFileOperation
|
|||||||
:
|
:
|
||||||
public masterUncollatedFileOperation
|
public masterUncollatedFileOperation
|
||||||
{
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Any initialisation steps after constructing
|
//- Any initialisation steps after constructing
|
||||||
@ -76,9 +82,6 @@ protected:
|
|||||||
|
|
||||||
// Protected Data
|
// Protected Data
|
||||||
|
|
||||||
//- Any communicator allocated by me
|
|
||||||
const label myComm_;
|
|
||||||
|
|
||||||
//- Threaded writer
|
//- Threaded writer
|
||||||
mutable OFstreamCollator writer_;
|
mutable OFstreamCollator writer_;
|
||||||
|
|
||||||
|
|||||||
@ -149,7 +149,8 @@ Foam::fileOperations::hostCollatedFileOperation::hostCollatedFileOperation
|
|||||||
(Pstream::parRun() ? labelList() : ioRanks()), // processor dirs
|
(Pstream::parRun() ? labelList() : ioRanks()), // processor dirs
|
||||||
typeName,
|
typeName,
|
||||||
false // verbose
|
false // verbose
|
||||||
)
|
),
|
||||||
|
managedComm_(comm_)
|
||||||
{
|
{
|
||||||
init(verbose);
|
init(verbose);
|
||||||
}
|
}
|
||||||
@ -159,9 +160,9 @@ Foam::fileOperations::hostCollatedFileOperation::hostCollatedFileOperation
|
|||||||
|
|
||||||
Foam::fileOperations::hostCollatedFileOperation::~hostCollatedFileOperation()
|
Foam::fileOperations::hostCollatedFileOperation::~hostCollatedFileOperation()
|
||||||
{
|
{
|
||||||
if (comm_ != -1 && comm_ != UPstream::worldComm)
|
if (UPstream::isUserComm(managedComm_))
|
||||||
{
|
{
|
||||||
UPstream::freeCommunicator(comm_);
|
UPstream::freeCommunicator(managedComm_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2017-2018 OpenFOAM Foundation
|
Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -77,6 +77,12 @@ class hostCollatedFileOperation
|
|||||||
:
|
:
|
||||||
public collatedFileOperation
|
public collatedFileOperation
|
||||||
{
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Any initialisation steps after constructing
|
//- Any initialisation steps after constructing
|
||||||
|
|||||||
@ -295,6 +295,42 @@ Foam::fileOperation::sortTimes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::fileOperation::uniformFile(const fileNameList& names)
|
||||||
|
{
|
||||||
|
if (names.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& object0 = names[0];
|
||||||
|
|
||||||
|
for (label i = 1; i < names.size(); ++i)
|
||||||
|
{
|
||||||
|
if (object0 != names[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::fileOperation::uniformFile(const label comm, const fileName& name)
|
||||||
|
{
|
||||||
|
if (!Pstream::parRun())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName masterName(name);
|
||||||
|
|
||||||
|
Pstream::broadcast(masterName, comm);
|
||||||
|
|
||||||
|
return returnReduceAnd((masterName == name), comm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::fileMonitor& Foam::fileOperation::monitor() const
|
Foam::fileMonitor& Foam::fileOperation::monitor() const
|
||||||
@ -710,6 +746,18 @@ Foam::fileOperation::New
|
|||||||
bool verbose
|
bool verbose
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (handlerType.empty())
|
||||||
|
{
|
||||||
|
if (fileOperation::defaultFileHandler.empty())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "defaultFileHandler name is undefined" << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileOperation::New(fileOperation::defaultFileHandler, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
DebugInFunction
|
DebugInFunction
|
||||||
<< "Constructing fileHandler" << endl;
|
<< "Constructing fileHandler" << endl;
|
||||||
|
|
||||||
@ -1511,37 +1559,56 @@ const Foam::fileOperation& Foam::fileHandler()
|
|||||||
{
|
{
|
||||||
if (!fileOperation::fileHandlerPtr_)
|
if (!fileOperation::fileHandlerPtr_)
|
||||||
{
|
{
|
||||||
word handler(Foam::getEnv("FOAM_FILEHANDLER"));
|
word handlerType(Foam::getEnv("FOAM_FILEHANDLER"));
|
||||||
|
|
||||||
if (handler.empty())
|
if (handlerType.empty())
|
||||||
{
|
{
|
||||||
handler = fileOperation::defaultFileHandler;
|
handlerType = fileOperation::defaultFileHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileOperation::fileHandlerPtr_ = fileOperation::New(handler, true);
|
fileOperation::fileHandlerPtr_ = fileOperation::New(handlerType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *fileOperation::fileHandlerPtr_;
|
return *fileOperation::fileHandlerPtr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::fileOperation>
|
||||||
|
Foam::fileHandler(std::nullptr_t)
|
||||||
|
{
|
||||||
|
return autoPtr<fileOperation>(fileOperation::fileHandlerPtr_.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::autoPtr<Foam::fileOperation>
|
Foam::autoPtr<Foam::fileOperation>
|
||||||
Foam::fileHandler(autoPtr<fileOperation>&& newHandler)
|
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
|
if
|
||||||
(
|
(
|
||||||
newHandler
|
newHandler.get() != nullptr
|
||||||
&& fileOperation::fileHandlerPtr_
|
&& newHandler.get() != fileOperation::fileHandlerPtr_.get()
|
||||||
&& newHandler->type() == fileOperation::fileHandlerPtr_->type()
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return nullptr; // No change
|
old.reset(newHandler.release());
|
||||||
|
old.swap(fileOperation::fileHandlerPtr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
autoPtr<fileOperation> old(std::move(fileOperation::fileHandlerPtr_));
|
|
||||||
|
|
||||||
fileOperation::fileHandlerPtr_ = std::move(newHandler);
|
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -196,6 +196,9 @@ public:
|
|||||||
const bool distributedRoots = false
|
const bool distributedRoots = false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Clone fileHandler
|
||||||
|
/// virtual autoPtr<fileOperation> clone() const = 0;
|
||||||
|
|
||||||
|
|
||||||
// Declare run-time constructor selection table
|
// Declare run-time constructor selection table
|
||||||
|
|
||||||
@ -213,7 +216,8 @@ public:
|
|||||||
|
|
||||||
// Selectors
|
// Selectors
|
||||||
|
|
||||||
//- Select fileHandler-type
|
//- Select fileHandler-type.
|
||||||
|
//- Uses defaultFileHandler if the handlerType is empty.
|
||||||
static autoPtr<fileOperation> New
|
static autoPtr<fileOperation> New
|
||||||
(
|
(
|
||||||
const word& handlerType,
|
const word& handlerType,
|
||||||
@ -235,6 +239,12 @@ public:
|
|||||||
const word& constantName = "constant"
|
const word& constantName = "constant"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- True if the file names are identical. False on an empty list
|
||||||
|
static bool uniformFile(const fileNameList& names);
|
||||||
|
|
||||||
|
//- True if the file name is identical on all ranks
|
||||||
|
static bool uniformFile(const label comm, const fileName& name);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
@ -628,11 +638,21 @@ inline Ostream& operator<<(Ostream& os, const fileOperation::pathType b)
|
|||||||
|
|
||||||
// Note: defined in fileOperation.C
|
// Note: defined in fileOperation.C
|
||||||
|
|
||||||
//- Get current file handler
|
//- Return the current file handler.
|
||||||
|
//- Will create the default file handler if necessary.
|
||||||
const fileOperation& fileHandler();
|
const fileOperation& fileHandler();
|
||||||
|
|
||||||
//- Replace, reset file handler.
|
//- Delete current file handler.
|
||||||
// \return old handler on change, null otherwise
|
// \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
|
||||||
autoPtr<fileOperation> fileHandler(autoPtr<fileOperation>&& newHandler);
|
autoPtr<fileOperation> fileHandler(autoPtr<fileOperation>&& newHandler);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -474,24 +474,6 @@ Foam::fileOperations::masterUncollatedFileOperation::localObjectPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::fileOperations::masterUncollatedFileOperation::uniformFile
|
|
||||||
(
|
|
||||||
const fileNameList& filePaths
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const fileName& object0 = filePaths[0];
|
|
||||||
|
|
||||||
for (label i = 1; i < filePaths.size(); i++)
|
|
||||||
{
|
|
||||||
if (filePaths[i] != object0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::fileOperations::masterUncollatedFileOperation::readAndSend
|
void Foam::fileOperations::masterUncollatedFileOperation::readAndSend
|
||||||
(
|
(
|
||||||
const fileName& filePath,
|
const fileName& filePath,
|
||||||
@ -763,7 +745,7 @@ masterUncollatedFileOperation
|
|||||||
subRanks(Pstream::nProcs())
|
subRanks(Pstream::nProcs())
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
myComm_(comm_)
|
managedComm_(comm_)
|
||||||
{
|
{
|
||||||
init(verbose);
|
init(verbose);
|
||||||
}
|
}
|
||||||
@ -777,7 +759,7 @@ masterUncollatedFileOperation
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
fileOperation(comm),
|
fileOperation(comm),
|
||||||
myComm_(-1)
|
managedComm_(-1) // Externally managed
|
||||||
{
|
{
|
||||||
init(verbose);
|
init(verbose);
|
||||||
}
|
}
|
||||||
@ -788,9 +770,9 @@ masterUncollatedFileOperation
|
|||||||
Foam::fileOperations::masterUncollatedFileOperation::
|
Foam::fileOperations::masterUncollatedFileOperation::
|
||||||
~masterUncollatedFileOperation()
|
~masterUncollatedFileOperation()
|
||||||
{
|
{
|
||||||
if (myComm_ != -1 && myComm_ != UPstream::worldComm)
|
if (UPstream::isUserComm(managedComm_))
|
||||||
{
|
{
|
||||||
UPstream::freeCommunicator(myComm_);
|
UPstream::freeCommunicator(managedComm_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -88,6 +88,12 @@ class masterUncollatedFileOperation
|
|||||||
:
|
:
|
||||||
public fileOperation
|
public fileOperation
|
||||||
{
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Any initialisation steps after constructing
|
//- Any initialisation steps after constructing
|
||||||
@ -97,9 +103,6 @@ protected:
|
|||||||
|
|
||||||
// Protected Data
|
// Protected Data
|
||||||
|
|
||||||
//- Any communicator allocated by me
|
|
||||||
const label myComm_;
|
|
||||||
|
|
||||||
//- Cached times for a given directory
|
//- Cached times for a given directory
|
||||||
mutable HashPtrTable<DynamicList<instant>> times_;
|
mutable HashPtrTable<DynamicList<instant>> times_;
|
||||||
|
|
||||||
@ -744,9 +747,6 @@ public:
|
|||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
||||||
//- Same file?
|
|
||||||
static bool uniformFile(const fileNameList&);
|
|
||||||
|
|
||||||
//- Get sorted list of times
|
//- Get sorted list of times
|
||||||
virtual instantList findTimes(const fileName&, const word&) const;
|
virtual instantList findTimes(const fileName&, const word&) const;
|
||||||
|
|
||||||
|
|||||||
@ -193,12 +193,24 @@ Foam::fileOperations::uncollatedFileOperation::uncollatedFileOperation
|
|||||||
bool verbose
|
bool verbose
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
fileOperation(Pstream::worldComm)
|
fileOperation(UPstream::worldComm),
|
||||||
|
managedComm_(-1) // worldComm is externally managed
|
||||||
{
|
{
|
||||||
init(verbose);
|
init(verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::fileOperations::uncollatedFileOperation::~uncollatedFileOperation()
|
||||||
|
{
|
||||||
|
if (UPstream::isUserComm(managedComm_))
|
||||||
|
{
|
||||||
|
UPstream::freeCommunicator(managedComm_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
|
||||||
|
|
||||||
bool Foam::fileOperations::uncollatedFileOperation::mkDir
|
bool Foam::fileOperations::uncollatedFileOperation::mkDir
|
||||||
|
|||||||
@ -53,6 +53,12 @@ class uncollatedFileOperation
|
|||||||
:
|
:
|
||||||
public fileOperation
|
public fileOperation
|
||||||
{
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Any initialisation steps after constructing
|
//- Any initialisation steps after constructing
|
||||||
@ -95,7 +101,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~uncollatedFileOperation() = default;
|
virtual ~uncollatedFileOperation();
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|||||||
Reference in New Issue
Block a user