ENH: codedFixedValue: refactor coded

This commit is contained in:
mattijs
2011-10-24 21:33:16 +01:00
parent 1cc1ddcacf
commit cd64f1762f
7 changed files with 573 additions and 589 deletions

View File

@ -193,6 +193,7 @@ dll = db/dynamicLibrary
$(dll)/dlLibraryTable/dlLibraryTable.C $(dll)/dlLibraryTable/dlLibraryTable.C
$(dll)/dynamicCode/dynamicCode.C $(dll)/dynamicCode/dynamicCode.C
$(dll)/dynamicCode/dynamicCodeContext.C $(dll)/dynamicCode/dynamicCodeContext.C
$(dll)/codedBase/codedBase.C
db/functionObjects/functionObject/functionObject.C db/functionObjects/functionObject/functionObject.C
db/functionObjects/functionObjectList/functionObjectList.C db/functionObjects/functionObjectList/functionObjectList.C

View File

@ -0,0 +1,288 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 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/>.
\*---------------------------------------------------------------------------*/
#include "codedBase.H"
#include "SHA1Digest.H"
#include "dynamicCode.H"
#include "dynamicCodeContext.H"
#include "dlLibraryTable.H"
#include "PstreamReduceOps.H"
#include "OSspecific.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void* Foam::codedBase::loadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const
{
void* lib = 0;
// avoid compilation by loading an existing library
if (!libPath.empty())
{
if (libs().open(libPath, false))
{
lib = libs().findLibrary(libPath);
// verify the loaded version and unload if needed
if (lib)
{
// provision for manual execution of code after loading
if (dlSymFound(lib, globalFuncName))
{
loaderFunctionType function =
reinterpret_cast<loaderFunctionType>
(
dlSym(lib, globalFuncName)
);
if (function)
{
(*function)(true); // force load
}
else
{
FatalIOErrorIn
(
"codedBase::updateLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName
<< nl << "from " << libPath << exit(FatalIOError);
}
}
else
{
FatalIOErrorIn
(
"codedBase::loadLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName << nl
<< "from " << libPath << exit(FatalIOError);
lib = 0;
if (!libs().close(libPath, false))
{
FatalIOErrorIn
(
"codedBase::loadLibrary()",
contextDict
) << "Failed unloading library "
<< libPath
<< exit(FatalIOError);
}
}
}
}
}
return lib;
}
void Foam::codedBase::unloadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const
{
void* lib = 0;
if (libPath.empty())
{
return;
}
lib = libs().findLibrary(libPath);
if (!lib)
{
return;
}
// provision for manual execution of code before unloading
if (dlSymFound(lib, globalFuncName))
{
loaderFunctionType function =
reinterpret_cast<loaderFunctionType>
(
dlSym(lib, globalFuncName)
);
if (function)
{
(*function)(false); // force unload
}
else
{
FatalIOErrorIn
(
"codedBase::unloadLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName << nl
<< "from " << libPath << exit(FatalIOError);
}
}
if (!libs().close(libPath, false))
{
FatalIOErrorIn
(
"codedBase::updateLibrary()",
contextDict
) << "Failed unloading library " << libPath
<< exit(FatalIOError);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::codedBase::createLibrary
(
dynamicCode& dynCode,
const dynamicCodeContext& context
) const
{
bool create = Pstream::master();
if (create)
{
// Write files for new library
if (!dynCode.upToDate(context))
{
// filter with this context
dynCode.reset(context);
this->prepare(dynCode, context);
if (!dynCode.copyOrCreateFiles(true))
{
FatalIOErrorIn
(
"codedBase::createLibrary(..)",
context.dict()
) << "Failed writing files for" << nl
<< dynCode.libRelPath() << nl
<< exit(FatalIOError);
}
}
if (!dynCode.wmakeLibso())
{
FatalIOErrorIn
(
"codedBase::createLibrary(..)",
context.dict()
) << "Failed wmake " << dynCode.libRelPath() << nl
<< exit(FatalIOError);
}
}
// all processes must wait for compile to finish
reduce(create, orOp<bool>());
}
void Foam::codedBase::updateLibrary
(
const word& redirectType
) const
{
const dictionary& dict = this->codeDict();
dynamicCode::checkSecurity
(
"codedBase::updateLibrary()",
dict
);
dynamicCodeContext context(dict);
// codeName: redirectType + _<sha1>
// codeDir : redirectType
dynamicCode dynCode
(
redirectType + context.sha1().str(true),
redirectType
);
const fileName libPath = dynCode.libPath();
// the correct library was already loaded => we are done
if (libs().findLibrary(libPath))
{
return;
}
Info<< "Using dynamicCode for " << this->description().c_str()
<< " at line " << dict.startLineNumber()
<< " in " << dict.name() << endl;
// remove instantiation of fvPatchField provided by library
this->clearRedirect();
// may need to unload old library
unloadLibrary
(
oldLibPath_,
dynamicCode::libraryBaseName(oldLibPath_),
context.dict()
);
// try loading an existing library (avoid compilation when possible)
if (!loadLibrary(libPath, dynCode.codeName(), context.dict()))
{
createLibrary(dynCode, context);
loadLibrary(libPath, dynCode.codeName(), context.dict());
}
// retain for future reference
oldLibPath_ = libPath;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::codedBase::codedBase()
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::codedBase::~codedBase()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,142 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 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::codedBase
Description
Base class for function objects and boundary conditions using dynamic code
SourceFiles
codedBase.C
\*---------------------------------------------------------------------------*/
#ifndef codedBase_H
#define codedBase_H
#include "dictionary.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class dynamicCode;
class dynamicCodeContext;
class dlLibraryTable;
/*---------------------------------------------------------------------------*\
Class codedBase Declaration
\*---------------------------------------------------------------------------*/
class codedBase
{
// Private data
//- Previously loaded library
mutable fileName oldLibPath_;
// Private Member Functions
//- Global loader/unloader function type
typedef void (*loaderFunctionType)(bool);
//- Load specified library and execute globalFuncName(true)
void* loadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const;
//- Execute globalFuncName(false) and unload specified library
void unloadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const;
//- Create library based on the dynamicCodeContext
void createLibrary(dynamicCode&, const dynamicCodeContext&) const;
//- Disallow default bitwise copy construct
codedBase(const codedBase&);
//- Disallow default bitwise assignment
void operator=(const codedBase&);
protected:
//- Update library as required
void updateLibrary
(
const word& redirectType
) const;
//- get the loaded dynamic libraries
virtual dlLibraryTable& libs() const = 0;
//- adapt the context for the current object
virtual void prepare
(
dynamicCode&,
const dynamicCodeContext &
) const = 0;
// Return a description (type + name) for the output
virtual string description() const = 0;
// Clear any redirected objects
virtual void clearRedirect() const = 0;
// Get the dictionary to initialize the codeContext
virtual const dictionary& codeDict() const = 0;
public:
// Constructors
//- Construct null
codedBase();
//- Destructor
virtual ~codedBase();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -26,19 +26,10 @@ License
#include "codedFixedValueFvPatchField.H" #include "codedFixedValueFvPatchField.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
#include "fvPatchFieldMapper.H" #include "fvPatchFieldMapper.H"
#include "surfaceFields.H"
#include "volFields.H" #include "volFields.H"
#include "dlLibraryTable.H"
#include "IFstream.H"
#include "OFstream.H"
#include "SHA1Digest.H"
#include "dynamicCode.H" #include "dynamicCode.H"
#include "dynamicCodeContext.H" #include "dynamicCodeContext.H"
#include "stringOps.H" #include "stringOps.H"
#include "IOdictionary.H"
#include <dlfcn.h>
#include <link.h>
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -53,142 +44,6 @@ const Foam::word Foam::codedFixedValueFvPatchField<Type>::codeTemplateH
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class Type>
void* Foam::codedFixedValueFvPatchField<Type>::loadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const
{
void* lib = 0;
// avoid compilation by loading an existing library
if (!libPath.empty())
{
dlLibraryTable& libs = const_cast<Time&>(this->db().time()).libs();
if (libs.open(libPath, false))
{
lib = libs.findLibrary(libPath);
// verify the loaded version and unload if needed
if (lib)
{
// provision for manual execution of code after loading
if (dlSymFound(lib, globalFuncName))
{
loaderFunctionType function =
reinterpret_cast<loaderFunctionType>
(
dlSym(lib, globalFuncName)
);
if (function)
{
(*function)(true); // force load
}
else
{
FatalIOErrorIn
(
"codedFixedValueFvPatchField<Type>::"
"updateLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName
<< nl << "from " << libPath << exit(FatalIOError);
}
}
else
{
FatalIOErrorIn
(
"codedFixedValueFvPatchField<Type>::loadLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName << nl
<< "from " << libPath << exit(FatalIOError);
lib = 0;
if (!libs.close(libPath, false))
{
FatalIOErrorIn
(
"codedFixedValueFvPatchField<Type>::loadLibrary()",
contextDict
) << "Failed unloading library "
<< libPath
<< exit(FatalIOError);
}
}
}
}
}
return lib;
}
template<class Type>
void Foam::codedFixedValueFvPatchField<Type>::unloadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const
{
void* lib = 0;
if (libPath.empty())
{
return;
}
dlLibraryTable& libs = const_cast<Time&>(this->db().time()).libs();
lib = libs.findLibrary(libPath);
if (!lib)
{
return;
}
// provision for manual execution of code before unloading
if (dlSymFound(lib, globalFuncName))
{
loaderFunctionType function =
reinterpret_cast<loaderFunctionType>
(
dlSym(lib, globalFuncName)
);
if (function)
{
(*function)(false); // force unload
}
else
{
FatalIOErrorIn
(
"codedFixedValueFvPatchField<Type>::unloadLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName << nl
<< "from " << libPath << exit(FatalIOError);
}
}
if (!libs.close(libPath, false))
{
FatalIOErrorIn
(
"codedFixedValueFvPatchField<Type>::"
"updateLibrary()",
contextDict
) << "Failed unloading library " << libPath
<< exit(FatalIOError);
}
}
template<class Type> template<class Type>
void Foam::codedFixedValueFvPatchField<Type>::setFieldTemplates void Foam::codedFixedValueFvPatchField<Type>::setFieldTemplates
( (
@ -238,144 +93,82 @@ const Foam::IOdictionary& Foam::codedFixedValueFvPatchField<Type>::dict() const
template<class Type> template<class Type>
void Foam::codedFixedValueFvPatchField<Type>::createLibrary Foam::dlLibraryTable& Foam::codedFixedValueFvPatchField<Type>::libs() const
{
return const_cast<dlLibraryTable&>(this->db().time().libs());
}
template<class Type>
void Foam::codedFixedValueFvPatchField<Type>::prepare
( (
dynamicCode& dynCode, dynamicCode& dynCode,
const dynamicCodeContext& context const dynamicCodeContext& context
) const ) const
{ {
bool create = Pstream::master(); // take no chances - typeName must be identical to redirectType_
dynCode.setFilterVariable("typeName", redirectType_);
if (create) // set TemplateType and FieldType filter variables
{ // (for fvPatchField)
// Write files for new library setFieldTemplates(dynCode);
if (!dynCode.upToDate(context))
{
// filter with this context
dynCode.reset(context);
// take no chances - typeName must be identical to redirectType_ // compile filtered C template
dynCode.setFilterVariable("typeName", redirectType_); dynCode.addCompileFile(codeTemplateC);
// set TemplateType and FieldType filter variables // copy filtered H template
// (for fvPatchField) dynCode.addCopyFile(codeTemplateH);
setFieldTemplates(dynCode);
// compile filtered C template
dynCode.addCompileFile(codeTemplateC);
// copy filtered H template
dynCode.addCopyFile(codeTemplateH);
// debugging: make BC verbose // debugging: make BC verbose
// dynCode.setFilterVariable("verbose", "true"); // dynCode.setFilterVariable("verbose", "true");
// Info<<"compile " << redirectType_ << " sha1: " // Info<<"compile " << redirectType_ << " sha1: "
// << context.sha1() << endl; // << context.sha1() << endl;
// define Make/options // define Make/options
dynCode.setMakeOptions dynCode.setMakeOptions
( (
"EXE_INC = -g \\\n" "EXE_INC = -g \\\n"
"-I$(LIB_SRC)/finiteVolume/lnInclude \\\n" "-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
+ context.options() + context.options()
+ "\n\nLIB_LIBS = \\\n" + "\n\nLIB_LIBS = \\\n"
+ " -lOpenFOAM \\\n" + " -lOpenFOAM \\\n"
+ " -lfiniteVolume \\\n" + " -lfiniteVolume \\\n"
+ context.libs() + context.libs()
); );
if (!dynCode.copyOrCreateFiles(true))
{
FatalIOErrorIn
(
"codedFixedValueFvPatchField<Type>::createLibrary(..)",
context.dict()
) << "Failed writing files for" << nl
<< dynCode.libRelPath() << nl
<< exit(FatalIOError);
}
}
if (!dynCode.wmakeLibso())
{
FatalIOErrorIn
(
"codedFixedValueFvPatchField<Type>::createLibrary(..)",
context.dict()
) << "Failed wmake " << dynCode.libRelPath() << nl
<< exit(FatalIOError);
}
}
// all processes must wait for compile to finish
reduce(create, orOp<bool>());
} }
template<class Type> template<class Type>
void Foam::codedFixedValueFvPatchField<Type>::updateLibrary() const const Foam::dictionary& Foam::codedFixedValueFvPatchField<Type>::codeDict()
const
{ {
dynamicCode::checkSecurity
(
"codedFixedValueFvPatchField<Type>::updateLibrary()",
dict_
);
// use system/codeDict or in-line // use system/codeDict or in-line
const dictionary& codeDict = return
( (
dict_.found("code") dict_.found("code")
? dict_ ? dict_
: this->dict().subDict(redirectType_) : this->dict().subDict(redirectType_)
); );
}
dynamicCodeContext context(codeDict);
// codeName: redirectType + _<sha1>
// codeDir : redirectType
dynamicCode dynCode
(
redirectType_ + context.sha1().str(true),
redirectType_
);
const fileName libPath = dynCode.libPath();
// the correct library was already loaded => we are done template<class Type>
if (const_cast<Time&>(this->db().time()).libs().findLibrary(libPath)) Foam::string Foam::codedFixedValueFvPatchField<Type>::description() const
{ {
return; return
} "patch "
+ this->patch().name()
Info<< "Using dynamicCode for patch " << this->patch().name() + " on field "
<< " on field " << this->dimensionedInternalField().name() << nl + this->dimensionedInternalField().name();
<< "at line " << codeDict.startLineNumber() }
<< " in " << codeDict.name() << endl;
template<class Type>
void Foam::codedFixedValueFvPatchField<Type>::clearRedirect() const
{
// remove instantiation of fvPatchField provided by library // remove instantiation of fvPatchField provided by library
redirectPatchFieldPtr_.clear(); redirectPatchFieldPtr_.clear();
// may need to unload old library
unloadLibrary
(
oldLibPath_,
dynamicCode::libraryBaseName(oldLibPath_),
context.dict()
);
// try loading an existing library (avoid compilation when possible)
if (!loadLibrary(libPath, dynCode.codeName(), context.dict()))
{
createLibrary(dynCode, context);
loadLibrary(libPath, dynCode.codeName(), context.dict());
}
// retain for future reference
oldLibPath_ = libPath;
} }
@ -389,7 +182,7 @@ Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(p, iF), fixedValueFvPatchField<Type>(p, iF),
oldLibPath_(), codedBase(),
redirectPatchFieldPtr_() redirectPatchFieldPtr_()
{} {}
@ -404,9 +197,9 @@ Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(ptf, p, iF, mapper), fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
codedBase(),
dict_(ptf.dict_), dict_(ptf.dict_),
redirectType_(ptf.redirectType_), redirectType_(ptf.redirectType_),
oldLibPath_(ptf.oldLibPath_),
redirectPatchFieldPtr_() redirectPatchFieldPtr_()
{} {}
@ -420,12 +213,12 @@ Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(p, iF, dict), fixedValueFvPatchField<Type>(p, iF, dict),
codedBase(),
dict_(dict), dict_(dict),
redirectType_(dict.lookup("redirectType")), redirectType_(dict.lookup("redirectType")),
oldLibPath_(),
redirectPatchFieldPtr_() redirectPatchFieldPtr_()
{ {
updateLibrary(); updateLibrary(redirectType_);
} }
@ -436,9 +229,9 @@ Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(ptf), fixedValueFvPatchField<Type>(ptf),
codedBase(),
dict_(ptf.dict_), dict_(ptf.dict_),
redirectType_(ptf.redirectType_), redirectType_(ptf.redirectType_),
oldLibPath_(ptf.oldLibPath_),
redirectPatchFieldPtr_() redirectPatchFieldPtr_()
{} {}
@ -451,9 +244,9 @@ Foam::codedFixedValueFvPatchField<Type>::codedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(ptf, iF), fixedValueFvPatchField<Type>(ptf, iF),
codedBase(),
dict_(ptf.dict_), dict_(ptf.dict_),
redirectType_(ptf.redirectType_), redirectType_(ptf.redirectType_),
oldLibPath_(ptf.oldLibPath_),
redirectPatchFieldPtr_() redirectPatchFieldPtr_()
{} {}
@ -499,7 +292,7 @@ void Foam::codedFixedValueFvPatchField<Type>::updateCoeffs()
} }
// Make sure library containing user-defined fvPatchField is up-to-date // Make sure library containing user-defined fvPatchField is up-to-date
updateLibrary(); updateLibrary(redirectType_);
const fvPatchField<Type>& fvp = redirectPatchField(); const fvPatchField<Type>& fvp = redirectPatchField();
@ -519,7 +312,7 @@ void Foam::codedFixedValueFvPatchField<Type>::evaluate
) )
{ {
// Make sure library containing user-defined fvPatchField is up-to-date // Make sure library containing user-defined fvPatchField is up-to-date
updateLibrary(); updateLibrary(redirectType_);
const fvPatchField<Type>& fvp = redirectPatchField(); const fvPatchField<Type>& fvp = redirectPatchField();

View File

@ -79,9 +79,7 @@ SourceFiles
#define codedFixedValueFvPatchField_H #define codedFixedValueFvPatchField_H
#include "fixedValueFvPatchFields.H" #include "fixedValueFvPatchFields.H"
#include "codedBase.H"
#include <dlfcn.h>
#include <link.h>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -100,7 +98,8 @@ class IOdictionary;
template<class Type> template<class Type>
class codedFixedValueFvPatchField class codedFixedValueFvPatchField
: :
public fixedValueFvPatchField<Type> public fixedValueFvPatchField<Type>,
public codedBase
{ {
// Private data // Private data
@ -109,51 +108,29 @@ class codedFixedValueFvPatchField
const word redirectType_; const word redirectType_;
//- Previously loaded library
mutable fileName oldLibPath_;
mutable autoPtr<fvPatchField<Type> > redirectPatchFieldPtr_; mutable autoPtr<fvPatchField<Type> > redirectPatchFieldPtr_;
// Private Member Functions // Private Member Functions
const IOdictionary& dict() const; const IOdictionary& dict() const;
//- Global loader/unloader function type
typedef void (*loaderFunctionType)(bool);
static int collectLibsCallback
(
struct dl_phdr_info *info,
size_t size,
void *data
);
//- Load specified library and execute globalFuncName(true)
void* loadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const;
//- Execute globalFuncName(false) and unload specified library
void unloadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const;
//- Set the rewrite vars controlling the Type //- Set the rewrite vars controlling the Type
static void setFieldTemplates(dynamicCode& dynCode); static void setFieldTemplates(dynamicCode& dynCode);
//- Create library based on the dynamicCodeContext //- get the loaded dynamic libraries
void createLibrary(dynamicCode&, const dynamicCodeContext&) const; virtual dlLibraryTable& libs() const;
//- Update library as required //- adapt the context for the current object
void updateLibrary() const; virtual void prepare(dynamicCode&, const dynamicCodeContext&) const;
// Return a description (type + name) for the output
virtual string description() const;
// Clear the ptr to the redirected object
virtual void clearRedirect() const;
// Get the dictionary to initialize the codeContext
virtual const dictionary& codeDict() const;
public: public:

View File

@ -49,271 +49,71 @@ namespace Foam
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void* Foam::codedFunctionObject::loadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const
{
void* lib = 0;
// avoid compilation by loading an existing library
if (!libPath.empty())
{
dlLibraryTable& libs = const_cast<Time&>(time_).libs();
if (libs.open(libPath, false))
{
lib = libs.findLibrary(libPath);
// verify the loaded version and unload if needed
if (lib)
{
// provision for manual execution of code after loading
if (dlSymFound(lib, globalFuncName))
{
loaderFunctionType function =
reinterpret_cast<loaderFunctionType>
(
dlSym(lib, globalFuncName)
);
if (function)
{
(*function)(true); // force load
}
else
{
FatalIOErrorIn
(
"codedFunctionObject::updateLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName
<< nl << "from " << libPath << exit(FatalIOError);
}
}
else
{
FatalIOErrorIn
(
"codedFunctionObject::loadLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName << nl
<< "from " << libPath << exit(FatalIOError);
lib = 0;
if (!libs.close(libPath, false))
{
FatalIOErrorIn
(
"codedFunctionObject::loadLibrary()",
contextDict
) << "Failed unloading library "
<< libPath
<< exit(FatalIOError);
}
}
}
}
}
return lib;
}
void Foam::codedFunctionObject::unloadLibrary
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const
{
void* lib = 0;
if (libPath.empty())
{
return;
}
dlLibraryTable& libs = const_cast<Time&>(time_).libs();
lib = libs.findLibrary(libPath);
if (!lib)
{
return;
}
// provision for manual execution of code before unloading
if (dlSymFound(lib, globalFuncName))
{
loaderFunctionType function =
reinterpret_cast<loaderFunctionType>
(
dlSym(lib, globalFuncName)
);
if (function)
{
(*function)(false); // force unload
}
else
{
FatalIOErrorIn
(
"codedFunctionObject::unloadLibrary()",
contextDict
) << "Failed looking up symbol " << globalFuncName << nl
<< "from " << libPath << exit(FatalIOError);
}
}
if (!libs.close(libPath, false))
{
FatalIOErrorIn
(
"codedFunctionObject::"
"updateLibrary()",
contextDict
) << "Failed unloading library " << libPath
<< exit(FatalIOError);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::codedFunctionObject::createLibrary void Foam::codedFunctionObject::prepare
( (
dynamicCode& dynCode, dynamicCode& dynCode,
const dynamicCodeContext& context const dynamicCodeContext& context
) const ) const
{ {
bool create = Pstream::master(); // Set additional rewrite rules
dynCode.setFilterVariable("typeName", redirectType_);
dynCode.setFilterVariable("codeRead", codeRead_);
dynCode.setFilterVariable("codeExecute", codeExecute_);
dynCode.setFilterVariable("codeEnd", codeEnd_);
//dynCode.setFilterVariable("codeWrite", codeWrite_);
if (create) // compile filtered C template
{ dynCode.addCompileFile("functionObjectTemplate.C");
// Write files for new library dynCode.addCompileFile("FilterFunctionObjectTemplate.C");
if (!dynCode.upToDate(context))
{
// filter with this context
dynCode.reset(context);
// Set additional rewrite rules // copy filtered H template
dynCode.setFilterVariable("typeName", redirectType_); dynCode.addCopyFile("FilterFunctionObjectTemplate.H");
dynCode.setFilterVariable("codeRead", codeRead_); dynCode.addCopyFile("functionObjectTemplate.H");
dynCode.setFilterVariable("codeExecute", codeExecute_); dynCode.addCopyFile("IOfunctionObjectTemplate.H");
dynCode.setFilterVariable("codeEnd", codeEnd_);
//dynCode.setFilterVariable("codeWrite", codeWrite_);
// compile filtered C template // debugging: make BC verbose
dynCode.addCompileFile("functionObjectTemplate.C"); // dynCode.setFilterVariable("verbose", "true");
dynCode.addCompileFile("FilterFunctionObjectTemplate.C"); // Info<<"compile " << redirectType_ << " sha1: "
// << context.sha1() << endl;
// copy filtered H template // define Make/options
dynCode.addCopyFile("FilterFunctionObjectTemplate.H"); dynCode.setMakeOptions
dynCode.addCopyFile("functionObjectTemplate.H"); (
dynCode.addCopyFile("IOfunctionObjectTemplate.H"); "EXE_INC = -g \\\n"
"-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
// debugging: make BC verbose + context.options()
// dynCode.setFilterVariable("verbose", "true"); + "\n\nLIB_LIBS = \\\n"
// Info<<"compile " << redirectType_ << " sha1: " + " -lOpenFOAM \\\n"
// << context.sha1() << endl; + " -lfiniteVolume \\\n"
+ context.libs()
// define Make/options );
dynCode.setMakeOptions
(
"EXE_INC = -g \\\n"
"-I$(LIB_SRC)/finiteVolume/lnInclude \\\n"
+ context.options()
+ "\n\nLIB_LIBS = \\\n"
+ " -lOpenFOAM \\\n"
+ " -lfiniteVolume \\\n"
+ context.libs()
);
if (!dynCode.copyOrCreateFiles(true))
{
FatalIOErrorIn
(
"codedFunctionObject::createLibrary(..)",
context.dict()
) << "Failed writing files for" << nl
<< dynCode.libRelPath() << nl
<< exit(FatalIOError);
}
}
if (!dynCode.wmakeLibso())
{
FatalIOErrorIn
(
"codedFunctionObject::createLibrary(..)",
context.dict()
) << "Failed wmake " << dynCode.libRelPath() << nl
<< exit(FatalIOError);
}
}
// all processes must wait for compile to finish
reduce(create, orOp<bool>());
} }
void Foam::codedFunctionObject::updateLibrary() const Foam::dlLibraryTable& Foam::codedFunctionObject::libs() const
{ {
dynamicCode::checkSecurity return const_cast<Time&>(time_).libs();
( }
"codedFunctionObject::updateLibrary()",
dict_
);
dynamicCodeContext context(dict_);
// codeName: redirectType + _<sha1>
// codeDir : redirectType
dynamicCode dynCode
(
redirectType_ + context.sha1().str(true),
redirectType_
);
const fileName libPath = dynCode.libPath();
// the correct library was already loaded => we are done Foam::string Foam::codedFunctionObject::description() const
if (const_cast<Time&>(time_).libs().findLibrary(libPath)) {
{ return "functionObject " + name();
return; }
}
Info<< "Using dynamicCode for functionObject " << name()
<< " at line " << dict_.startLineNumber()
<< " in " << dict_.name() << endl;
// remove instantiation of fvPatchField provided by library void Foam::codedFunctionObject::clearRedirect() const
{
redirectFunctionObjectPtr_.clear(); redirectFunctionObjectPtr_.clear();
}
// may need to unload old library
unloadLibrary
(
oldLibPath_,
dynamicCode::libraryBaseName(oldLibPath_),
context.dict()
);
// try loading an existing library (avoid compilation when possible) const Foam::dictionary& Foam::codedFunctionObject::codeDict() const
if (!loadLibrary(libPath, dynCode.codeName(), context.dict())) {
{ return dict_;
createLibrary(dynCode, context);
loadLibrary(libPath, dynCode.codeName(), context.dict());
}
// retain for future reference
oldLibPath_ = libPath;
} }
@ -323,14 +123,18 @@ Foam::codedFunctionObject::codedFunctionObject
( (
const word& name, const word& name,
const Time& time, const Time& time,
const dictionary& dict const dictionary& dict,
bool readNow
) )
: :
functionObject(name), functionObject(name),
time_(time), codedBase(),
dict_(dict) time_(time)
{ {
read(dict_); if (readNow)
{
read(dict_);
}
} }
@ -363,21 +167,21 @@ Foam::codedFunctionObject::redirectFunctionObject() const
bool Foam::codedFunctionObject::start() bool Foam::codedFunctionObject::start()
{ {
updateLibrary(); updateLibrary(redirectType_);
return redirectFunctionObject().start(); return redirectFunctionObject().start();
} }
bool Foam::codedFunctionObject::execute(const bool forceWrite) bool Foam::codedFunctionObject::execute(const bool forceWrite)
{ {
updateLibrary(); updateLibrary(redirectType_);
return redirectFunctionObject().execute(forceWrite); return redirectFunctionObject().execute(forceWrite);
} }
bool Foam::codedFunctionObject::end() bool Foam::codedFunctionObject::end()
{ {
updateLibrary(); updateLibrary(redirectType_);
return redirectFunctionObject().end(); return redirectFunctionObject().end();
} }
@ -440,7 +244,7 @@ bool Foam::codedFunctionObject::read(const dictionary& dict)
); );
} }
updateLibrary(); updateLibrary(redirectType_);
return redirectFunctionObject().read(dict); return redirectFunctionObject().read(dict);
} }

View File

@ -35,30 +35,22 @@ SourceFiles
#ifndef codedFunctionObject_H #ifndef codedFunctionObject_H
#define codedFunctionObject_H #define codedFunctionObject_H
#include "pointFieldFwd.H"
#include "functionObject.H" #include "functionObject.H"
#include "dictionary.H" #include "codedBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// Forward declaration of classes
class objectRegistry;
class dictionary;
class mapPolyMesh;
class dynamicCode;
class dynamicCodeContext;
class IOdictionary;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class codedFunctionObject Declaration Class codedFunctionObject Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
class codedFunctionObject class codedFunctionObject
: :
public functionObject public functionObject,
public codedBase
{ {
protected: protected:
@ -76,42 +68,28 @@ protected:
string codeExecute_; string codeExecute_;
string codeEnd_; string codeEnd_;
//- Previously loaded library
mutable fileName oldLibPath_;
//- Underlying functionObject //- Underlying functionObject
mutable autoPtr<functionObject> redirectFunctionObjectPtr_; mutable autoPtr<functionObject> redirectFunctionObjectPtr_;
// Private Member Functions
//- Global loader/unloader function type // Protected Member Functions
typedef void (*loaderFunctionType)(bool);
//- Load specified library and execute globalFuncName(true) //- get the loaded dynamic libraries
void* loadLibrary virtual dlLibraryTable& libs() const;
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const;
//- Execute globalFuncName(false) and unload specified library //- adapt the context for the current object
void unloadLibrary virtual void prepare(dynamicCode &,const dynamicCodeContext&) const;
(
const fileName& libPath,
const string& globalFuncName,
const dictionary& contextDict
) const;
// Return a description (type + name) for the output
virtual string description() const;
//- Create library based on the dynamicCodeContext // Clear any redirected objects
void createLibrary(dynamicCode&, const dynamicCodeContext&) const; virtual void clearRedirect() const;
//- Update library as required // Get the dictionary to initialize the codeContext
void updateLibrary() const; virtual const dictionary& codeDict() const;
//- Read relevant dictionary entries private:
void readDict();
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
codedFunctionObject(const codedFunctionObject&); codedFunctionObject(const codedFunctionObject&);
@ -134,7 +112,8 @@ public:
( (
const word& name, const word& name,
const Time& time, const Time& time,
const dictionary& dict const dictionary& dict,
bool readNow=true // allow child-classes to avoid compilation
); );