From 97cd3af1ff93a173355e82e5f16a783a8154eee3 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 1 Mar 2011 14:19:24 +0100 Subject: [PATCH] ENH: cleanup codeStream - use dynamicCode, dynamicCodeContext encapsulation Problems remain with codedFixedValueFvPatchScalarField: - readIfModified() notices change on system/codeDict, but the codeProperties::setUnmodified() means that only a single entry will get processed - it appears that while dlclose() may (or may not) be actually closing the library, there are probably still references about. This means that a subsequent reloading still points to the original functions and the lookup is not updated correctly. --- doc/changes/dynamicCode.org | 2 +- .../dynamicCode/codeStreamTemplate.C | 4 +- .../functionEntries/codeStream/codeStream.C | 61 ++-- .../functionEntries/codeStream/codeStream.H | 4 +- .../dynamicLibrary/dynamicCode/dynamicCode.C | 343 +++++++++++------- .../dynamicLibrary/dynamicCode/dynamicCode.H | 161 +++++--- .../codedFixedValueFvPatchScalarField.C | 269 ++++++++------ .../codedFixedValueFvPatchScalarField.H | 12 +- 8 files changed, 523 insertions(+), 333 deletions(-) diff --git a/doc/changes/dynamicCode.org b/doc/changes/dynamicCode.org index 1cd3d3338a..9ea400ef4b 100644 --- a/doc/changes/dynamicCode.org +++ b/doc/changes/dynamicCode.org @@ -13,7 +13,7 @@ provide the actual dictionary entry. The snippet gets provided as three sections of C++ code which just gets inserted into a template: - =code= section: the actual body of the code. It gets called with arguments - =const dictionary& dict, OStream& os= and the C++ code can do a + =OStream& os, const dictionary& dict= and the C++ code can do a =dict.lookup= to find current dictionary values. - optional =codeInclude= section: any #include statements to include OpenFOAM files. diff --git a/etc/codeTemplates/dynamicCode/codeStreamTemplate.C b/etc/codeTemplates/dynamicCode/codeStreamTemplate.C index 50a47e1b1a..35ff81f476 100644 --- a/etc/codeTemplates/dynamicCode/codeStreamTemplate.C +++ b/etc/codeTemplates/dynamicCode/codeStreamTemplate.C @@ -44,8 +44,8 @@ extern "C" { void ${typeName} ( - const dictionary& dict, - Ostream& os + Ostream& os, + const dictionary& dict ) { //{{{ begin code diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C index da2b637979..92a6b444f1 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C @@ -83,67 +83,61 @@ bool Foam::functionEntries::codeStream::execute // get code, codeInclude, codeOptions dynamicCodeContext context(codeDict); - // codeName: prefix_ + sha1 + // codeName: codeStream + _ // codeDir : _ dynamicCode dynCode ( - "codeStream_" + context.sha1().str(), - "_" + context.sha1().str() + "codeStream" + context.sha1().str(true), + context.sha1().str(true) ); // Load library if not already loaded // Version information is encoded in the libPath (encoded with the SHA1) const fileName libPath = dynCode.libPath(); + // see if library is loaded void* lib = dlLibraryTable::findLibrary(libPath); + bool reuseLib = false; + + // nothing loaded + // avoid compilation if possible by loading an existing library if (!lib && dlLibraryTable::open(libPath, false)) { lib = dlLibraryTable::findLibrary(libPath); + reuseLib = true; } - // did not load - need to compile it + + // create library if required if (!lib) { if (Pstream::master()) { if (!dynCode.upToDate(context)) { - Info<< "Creating new library in " - << dynCode.libPath() << endl; - - // filter C template - dynCode.addFilterFile(codeTemplateC); - // filter with this context - dynCode.setFilterContext(context); + dynCode.reset(context); - // Write Make/files - dynCode.addCreateFile - ( - "Make/files", - codeTemplateC + "\n\n" - + dynCode.libTarget() - ); + // compile filtered C template + dynCode.addCompileFile(codeTemplateC); - // Write Make/options - dynCode.addCreateFile + // define Make/options + dynCode.setMakeOptions ( - "Make/options", "EXE_INC = -g \\\n" + context.options() + "\n\nLIB_LIBS =" ); - if (!dynCode.copyFilesContents()) + if (!dynCode.copyOrCreateFiles(true)) { FatalIOErrorIn ( "functionEntries::codeStream::execute(..)", parentDict - ) << "Failed writing " << nl - // << copyFiles << endl - // << filesContents + ) << "Failed writing files for" << nl + << dynCode.libPath() << nl << exit(FatalIOError); } } @@ -160,8 +154,8 @@ bool Foam::functionEntries::codeStream::execute } // all processes must wait for compile - bool dummy = true; - reduce(dummy, orOp()); + bool waiting = true; + reduce(waiting, orOp()); if (!dlLibraryTable::open(libPath, false)) { @@ -175,15 +169,15 @@ bool Foam::functionEntries::codeStream::execute lib = dlLibraryTable::findLibrary(libPath); } - else + else if (reuseLib) { Info<< "Reusing library in " << libPath << endl; } - // Find the library handle. - void (*function)(const dictionary&, Ostream&); - function = reinterpret_cast + // Find the function handle in the library + void (*function)(Ostream&, const dictionary&); + function = reinterpret_cast ( dlSym(lib, dynCode.codeName()) ); @@ -199,8 +193,11 @@ bool Foam::functionEntries::codeStream::execute << " in library " << lib << exit(FatalIOError); } + // use function to write stream OStringStream os(is.format()); - (*function)(parentDict, os); + (*function)(os, parentDict); + + // get the entry from this stream IStringStream resultStream(os.str()); entry.read(parentDict, resultStream); diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H index e04bdceaa4..10e3262ca1 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H @@ -135,8 +135,8 @@ public: static bool execute ( const dictionary& parentDict, - primitiveEntry& entry, - Istream& is + primitiveEntry&, + Istream& ); }; diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C index b4c52afbb0..2493ad8d16 100644 --- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C +++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C @@ -33,6 +33,7 @@ License #include "dictionary.H" #include "dlLibraryTable.H" + // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // int Foam::dynamicCode::allowSystemOperations @@ -47,6 +48,9 @@ const Foam::word Foam::dynamicCode::codeTemplateEnvName const Foam::fileName Foam::dynamicCode::codeTemplateDirName = "codeTemplates/dynamicCode"; +const char* Foam::dynamicCode::libTargetRoot = + "LIB = $(PWD)/../platforms/$(WM_OPTIONS)/lib/lib"; + // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // @@ -78,7 +82,7 @@ void Foam::dynamicCode::copyAndFilter ISstream& is, OSstream& os, const HashTable& mapping -) const +) { if (!is.good()) { @@ -110,27 +114,26 @@ void Foam::dynamicCode::copyAndFilter // expanding according to env variables might cause too many // surprises stringOps::inplaceExpand(line, mapping); - - os << line.c_str() << nl; + os.writeQuoted(line, false) << nl; } while (is.good()); } -Foam::List -Foam::dynamicCode::resolveTemplates(const UList& names) +bool Foam::dynamicCode::resolveTemplates +( + const UList& templateNames, + DynamicList& resolvedFiles, + DynamicList& badFiles +) { // try to get template from FOAM_CODESTREAM_TEMPLATES const fileName templateDir(Foam::getEnv(codeTemplateEnvName)); - DynamicList badFiles(names.size()); - List resolved(names.size()); - - label nResolved = 0; - - forAll(names, fileI) + bool allOkay = true; + forAll(templateNames, fileI) { - const fileName& templateName = names[fileI]; + const fileName& templateName = templateNames[fileI]; fileName file; if (!templateDir.empty() && isDir(templateDir)) @@ -151,73 +154,186 @@ Foam::dynamicCode::resolveTemplates(const UList& names) if (file.empty()) { badFiles.append(templateName); + allOkay = false; } else { - resolved[nResolved++] = file; + resolvedFiles.append(file); } } - resolved.setSize(nResolved); + return allOkay; +} - if (!badFiles.empty()) + +bool Foam::dynamicCode::writeCommentSHA1(Ostream& os) const +{ + const bool hasSHA1 = filterVars_.found("SHA1sum"); + + if (hasSHA1) { - FatalErrorIn - ( - "dynamicCode::resolveTemplates(..)" - ) << "Could not find the code template(s): " - << badFiles << nl - << "Under the $" << codeTemplateDirName - << " directory or via via the ~OpenFOAM/" - << codeTemplateDirName << " expansion" - << exit(FatalError); + os << "/* dynamicCode:\n * SHA1 = "; + os.writeQuoted(filterVars_["SHA1sum"], false) << "\n */\n"; } - return resolved; + return hasSHA1; +} + + +bool Foam::dynamicCode::createMakeFiles() const +{ + // Create Make/files + if (compileFiles_.empty()) + { + return false; + } + + const fileName dstFile(this->codePath()/"Make/files"); + + // Create dir + mkDir(dstFile.path()); + + OFstream os(dstFile); + //Info<< "Writing to " << dstFile << endl; + if (!os.good()) + { + FatalErrorIn + ( + "dynamicCode::createMakeFiles()" + " const" + ) << "Failed writing " << dstFile + << exit(FatalError); + } + + writeCommentSHA1(os); + + // Write compile files + forAll(compileFiles_, fileI) + { + os.writeQuoted(compileFiles_[fileI], false) << nl; + } + + os << nl + << libTargetRoot << codeName_.c_str() << nl; + + return true; +} + + +bool Foam::dynamicCode::createMakeOptions() const +{ + // Create Make/options + if (compileFiles_.empty() || makeOptions_.empty()) + { + return false; + } + + const fileName dstFile(this->codePath()/"Make/options"); + + // Create dir + mkDir(dstFile.path()); + + OFstream os(dstFile); + //Info<< "Writing to " << dstFile << endl; + if (!os.good()) + { + FatalErrorIn + ( + "dynamicCode::createMakeOptions()" + " const" + ) << "Failed writing " << dstFile + << exit(FatalError); + } + + writeCommentSHA1(os); + os.writeQuoted(makeOptions_, false) << nl; + + return true; +} + + +bool Foam::dynamicCode::writeDigest(const SHA1Digest& sha1) const +{ + const fileName file = digestFile(); + mkDir(file.path()); + + OFstream os(file); + sha1.write(os, true) << nl; + + return os.good(); +} + + +bool Foam::dynamicCode::writeDigest(const std::string& sha1) const +{ + const fileName file = digestFile(); + mkDir(file.path()); + + OFstream os(file); + os << '_'; + os.writeQuoted(sha1, false) << nl; + + return os.good(); } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -Foam::dynamicCode::dynamicCode(const word& codeName) -: - codeName_(codeName), - codeDirName_(codeName) -{ - filterVars_.set("typeName", codeName_); - filterVars_.set("SHA1sum", SHA1Digest().str()); -} - Foam::dynamicCode::dynamicCode(const word& codeName, const word& codeDirName) : + codeRoot_(stringOps::expand("$FOAM_CASE/dynamicCode")), + libSubDir_(stringOps::expand("platforms/$WM_OPTIONS/lib")), codeName_(codeName), codeDirName_(codeDirName) { - filterVars_.set("typeName", codeName_); - filterVars_.set("SHA1sum", SHA1Digest().str()); + if (codeDirName_.empty()) + { + codeDirName_ = codeName_; + } + + clear(); } -// Foam::dynamicCode::dynamicCode(const dynamicCode& dc) -// : -// codeName_(dc.codeName_), -// copyFiles_(dc.copyFiles_), -// filesContents_(dc.filesContents_) -// {} - - // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::dynamicCode::clear() { - filterVars_.clear(); - filterFiles_.clear(); + compileFiles_.clear(); + copyFiles_.clear(); createFiles_.clear(); + filterVars_.clear(); filterVars_.set("typeName", codeName_); filterVars_.set("SHA1sum", SHA1Digest().str()); + + // provide default Make/options + makeOptions_ = + "EXE_INC = -g\n" + "\n\nLIB_LIBS = "; } +void Foam::dynamicCode::reset +( + const dynamicCodeContext& context +) +{ + clear(); + setFilterContext(context); +} + + +void Foam::dynamicCode::addCompileFile(const fileName& name) +{ + compileFiles_.append(name); +} + + +void Foam::dynamicCode::addCopyFile(const fileName& name) +{ + copyFiles_.append(name); +} + void Foam::dynamicCode::addCreateFile ( @@ -229,15 +345,6 @@ void Foam::dynamicCode::addCreateFile } -void Foam::dynamicCode::addFilterFile -( - const fileName& name -) -{ - filterFiles_.append(name); -} - - void Foam::dynamicCode::setFilterContext ( const dynamicCodeContext& context @@ -252,46 +359,31 @@ void Foam::dynamicCode::setFilterContext void Foam::dynamicCode::setFilterVariable ( const word& key, - const string& value + const std::string& value ) { filterVars_.set(key, value); } -Foam::fileName Foam::dynamicCode::codePath() const +void Foam::dynamicCode::setMakeOptions(const std::string& content) { - return stringOps::expand("$FOAM_CASE/dynamicCode/" + codeDirName_); + makeOptions_ = content; } -Foam::fileName Foam::dynamicCode::libPath() const +bool Foam::dynamicCode::copyOrCreateFiles(const bool verbose) const { - return - ( - stringOps::expand - ( - "$FOAM_CASE/dynamicCode/platforms/$WM_OPTIONS/lib/lib" - ) - + codeName_ + ".so" - ); -} + if (verbose) + { + Info<< "Creating new library in " << this->libPath() << endl; + } - -Foam::string Foam::dynamicCode::libTarget() const -{ - return "LIB = $(PWD)/../platforms/$(WM_OPTIONS)/lib/lib" + codeName_; -} - - - -bool Foam::dynamicCode::copyFilesContents() const -{ if (!allowSystemOperations) { FatalErrorIn ( - "dynamicCode::copyFilesContents(const fileName&) const" + "dynamicCode::copyOrCreateFiles() const" ) << "Loading a shared library using case-supplied code is not" << " enabled by default" << nl << "because of security issues. If you trust the code you can" @@ -307,7 +399,29 @@ bool Foam::dynamicCode::copyFilesContents() const << exit(FatalError); } - List resolvedFiles = resolveTemplates(filterFiles_); + const label nFiles = compileFiles_.size() + copyFiles_.size(); + + DynamicList resolvedFiles(nFiles); + DynamicList badFiles(nFiles); + + // resolve template, or add to bad-files + resolveTemplates(compileFiles_, resolvedFiles, badFiles); + resolveTemplates(copyFiles_, resolvedFiles, badFiles); + + if (!badFiles.empty()) + { + FatalErrorIn + ( + "dynamicCode::copyFilesContents(..)" + ) << "Could not find the code template(s): " + << badFiles << nl + << "Under the $" << codeTemplateEnvName + << " directory or via via the ~OpenFOAM/" + << codeTemplateDirName << " expansion" + << exit(FatalError); + } + + // Create dir const fileName outputDir = this->codePath(); @@ -345,7 +459,7 @@ bool Foam::dynamicCode::copyFilesContents() const << exit(FatalError); } - // variables mapping + // Copy lines while expanding variables copyAndFilter(is, os, filterVars_); } @@ -365,14 +479,21 @@ bool Foam::dynamicCode::copyFilesContents() const { FatalErrorIn ( - "dynamicCode::copyFilesContents()" + "dynamicCode::copyOrCreateFiles()" " const" ) << "Failed writing " << dstFile << exit(FatalError); } - os << createFiles_[fileI].second().c_str() << endl; + os.writeQuoted(createFiles_[fileI].second(), false) << nl; } + + // Create Make/files + Make/options + createMakeFiles(); + createMakeOptions(); + + writeDigest(filterVars_["SHA1sum"]); + return true; } @@ -393,38 +514,16 @@ bool Foam::dynamicCode::wmakeLibso() const } -bool Foam::dynamicCode::writeDigest -( - const fileName& dirName, - const SHA1Digest& sha1 -) const -{ - mkDir(dirName); - OFstream os(dirName/"SHA1Digest"); - os << sha1; - return os.good(); -} - - -Foam::SHA1Digest Foam::dynamicCode::readDigest(const fileName& dirName) const -{ - IFstream is(dirName/"SHA1Digest"); - return SHA1Digest(is); -} - - bool Foam::dynamicCode::upToDate(const SHA1Digest& sha1) const { - const fileName dirName = this->codePath(); - if (!exists(dirName/"SHA1Digest") || readDigest(dirName) != sha1) + const fileName file = digestFile(); + + if (!exists(file, false) || SHA1Digest(IFstream(file)()) != sha1) { - writeDigest(dirName, sha1); return false; } - else - { - return true; - } + + return true; } @@ -452,28 +551,4 @@ bool Foam::dynamicCode::upToDate(const dynamicCodeContext& context) const // } - -// bool Foam::dynamicCode::read(const dictionary& dict) -// { -// dict.lookup("createFiles") >> createFiles_; -// dict.lookup("filterFiles") >> filterFiles_; -// dict.lookup("filterVariables") >> filterVariables_; -// -// return true; -// } -// -// -// void Foam::dynamicCode::writeDict(Ostream& os) const -// { -// os.writeKeyword("createFiles") << createFiles_ -// << token::END_STATEMENT << nl; -// -// os.writeKeyword("filterFiles") << filterFiles_ -// << token::END_STATEMENT << nl; -// -// os.writeKeyword("filterVariables") << filterVariables_ -// << token::END_STATEMENT << nl; -// } - - // ************************************************************************* // diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H index d122486156..af7f996c08 100644 --- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H +++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H @@ -64,41 +64,86 @@ public: private: // Private data + //- Root for dynamic code compilation + fileName codeRoot_; + + //- Subdirectory name for loading libraries + const fileName libSubDir_; + //- Name for code word codeName_; //- Name for code subdirectory - mutable word codeDirName_; + word codeDirName_; - //- Variables to use during filtering - HashTable filterVars_; + //- Files to copy and filter + DynamicList compileFiles_; + + //- Files to copy and filter + DynamicList copyFiles_; //- Direct contents for files DynamicList createFiles_; - //- Files to copy and filter - DynamicList filterFiles_; + //- Variables to use during filtering + HashTable filterVars_; + + //- Contents for Make/options + std::string makeOptions_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + dynamicCode(const dynamicCode&); + + //- Disallow default bitwise assignment + void operator=(const dynamicCode&); protected: - void copyAndFilter + // Static data members + + //- Root of the LIB target for Make/files + static const char* libTargetRoot; + + + // Protected Member Functions + + //- Copy lines while expanding variables + static void copyAndFilter ( ISstream&, OSstream&, const HashTable& mapping - ) const; + ); //- Resolve code-templates via the codeTemplateEnvName // alternatively in the codeTemplateDirName via Foam::findEtcFile - static List resolveTemplates + static bool resolveTemplates ( - const UList& names + const UList& templateNames, + DynamicList& resolvedFiles, + DynamicList& badFiles ); + //- Write SHA1 value as C-comment + bool writeCommentSHA1(Ostream&) const; + + //- Copy/create Make/files prior to compilation + bool createMakeFiles() const; + + //- Copy/create Make/options prior to compilation + bool createMakeOptions() const; + + + //- Write digest to Make/SHA1Digest + bool writeDigest(const SHA1Digest&) const; + + //- Write digest to Make/SHA1Digest + bool writeDigest(const std::string&) const; - bool writeDigest(const fileName& dir, const SHA1Digest& sha1) const; - SHA1Digest readDigest(const fileName& dir) const; public: @@ -112,26 +157,25 @@ public: // Used when locating the codeTemplateName via Foam::findEtcFile static const fileName codeTemplateDirName; + //- Flag if system operations are allowed static int allowSystemOperations; // Static Member functions //- Check security for creating dynamic code - static void checkSecurity - ( - const char* title, - const dictionary& dict - ); + static void checkSecurity(const char* title, const dictionary&); // Constructors - //- Construct for a specified code name - dynamicCode(const word& codeName); - - //- Construct for a specified code name and directory name - dynamicCode(const word& codeName, const word& dirName); + //- Construct for a specified code name and code directory name + // Defaults to using the code name for the code directory name + dynamicCode + ( + const word& codeName, + const word& codeDirName = "" + ); // Member functions @@ -148,43 +192,76 @@ public: return codeDirName_; } - //- Clear variables and files + //- Root for dynamic code compilation + // Expanded from \$FOAM_CASE/dynamicCode + const fileName& codeRoot() const + { + return codeRoot_; + } + + //- Subdirectory name for loading libraries + // Expanded from platforms/\$WM_OPTIONS/lib + fileName libSubDir() const + { + return libSubDir_; + } + + //- Path for specified code name + // Corresponds to codeRoot()/codeDirName() + fileName codePath() const + { + return codeRoot_/codeDirName_; + } + + //- Library path for specified code name + // Corresponds to codeRoot()/libSubDir()/lib\.so + fileName libPath() const + { + return codeRoot_/libSubDir_/"lib" + codeName_ + ".so"; + } + + //- Path for SHA1Digest + // Corresponds to codePath()/Make/SHA1Digest + fileName digestFile() const + { + return codeRoot_/codeDirName_/"Make/SHA1Digest"; + } + + + //- Clear files and variables void clear(); + //- Clear files and reset variables to specified context + void reset(const dynamicCodeContext&); + + + //- Add a file template name, which will be found and filtered + void addCompileFile(const fileName& name); + + //- Add a file template name, which will be found and filtered + void addCopyFile(const fileName& name); //- Add a file to create with its contents. Will not be filtered void addCreateFile(const fileName& name, const string& contents); - //- Add a file template name, which will be found and filtered - void addFilterFile(const fileName& name); - //- Define filter variables for code, codeInclude, SHA1sum void setFilterContext(const dynamicCodeContext&); //- Define a filter variable - void setFilterVariable(const word& key, const string& value); + void setFilterVariable(const word& key, const std::string& value); + + //- Define contents for Make/options + void setMakeOptions(const std::string& content); - //- Local path for specified code name - // Expanded from \$FOAM_CASE/dynamicCode/codeDirName - fileName codePath() const; - - //- Local library path for specified code name - // Expanded from \$FOAM_CASE/dynamicCode/platforms/\$WM_OPTIONS/lib - fileName libPath() const; - - //- The library target path for Make/files - string libTarget() const; - - - //- Verify if the copied code is up-to-date + //- Verify if the copied code is up-to-date, based on Make/SHA1Digest bool upToDate(const dynamicCodeContext& context) const; - //- Verify if the copied code is up-to-date + //- Verify if the copied code is up-to-date, based on Make/SHA1Digest bool upToDate(const SHA1Digest& sha1) const; //- Copy/create files prior to compilation - bool copyFilesContents() const; + bool copyOrCreateFiles(const bool verbose = false) const; //- Compile a libso bool wmakeLibso() const; @@ -198,8 +275,6 @@ public: // //- Find the handle of the libPath() library // void* findLibrary() const; -// bool read(const dictionary&); -// void writeDict(Ostream&) const; }; diff --git a/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchScalarField.C index a467943f65..8175f1b5ed 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchScalarField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchScalarField.C @@ -82,55 +82,47 @@ void Foam::codedFixedValueFvPatchScalarField::createLibrary ( dynamicCode& dynCode, const dynamicCodeContext& context -) +) const { // Write files for new library if (Pstream::master() && !dynCode.upToDate(context)) { - Info<< "Creating new library in " << dynCode.libPath() << endl; - dynCode.clear(); - // filter with this context - dynCode.setFilterContext(context); + dynCode.reset(context); - // filter C/H template - dynCode.addFilterFile(codeTemplateC); - dynCode.addFilterFile(codeTemplateH); + // compile filtered C template + dynCode.addCompileFile(codeTemplateC); - // Make/files - dynCode.addCreateFile + // copy filtered H template + dynCode.addCopyFile(codeTemplateH); + + // define Make/options + dynCode.setMakeOptions ( - "Make/files", - codeTemplateC + "\n\n" - + dynCode.libTarget() - ); - - // Make/options - dynCode.addCreateFile - ( - "Make/options", "EXE_INC = -g \\\n" "-I$(LIB_SRC)/finiteVolume/lnInclude\\\n" + context.options() + "\n\nLIB_LIBS = " ); - if (!dynCode.copyFilesContents()) + if (!dynCode.copyOrCreateFiles(true)) { FatalIOErrorIn ( "codedFixedValueFvPatchScalarField::writeLibrary(..)", context.dict() - ) << "Failed writing " << nl - // << copyFiles << nl - // << filesContents + ) << "Failed writing files for" << nl + << dynCode.libPath() << nl << exit(FatalIOError); } } } -void Foam::codedFixedValueFvPatchScalarField::updateLibrary() +void Foam::codedFixedValueFvPatchScalarField::updateLibrary +( + bool firstTime +) const { dynamicCode::checkSecurity ( @@ -138,97 +130,124 @@ void Foam::codedFixedValueFvPatchScalarField::updateLibrary() dict_ ); - // use in-line or via codeProperties - const bool useInlineDict = dict_.found("code"); + // use codeProperties or in-line + const bool useCodeProps = !dict_.found("code"); - // determine code context (code, codeInclude, codeOptions) - dynamicCodeContext context + const dictionary& codeDict = ( - useInlineDict - ? dict_ - : this->dict().subDict(redirectType_) + useCodeProps + ? this->dict().subDict(redirectType_) + : dict_ ); - // NOTE: probably don't need codeProperties anymore - // since we use the sha1 directly - if (!useInlineDict) - { - this->dict().setUnmodified(); - } - + autoPtr contextPtr; // write code into redirectType_ subdir as well dynamicCode dynCode(redirectType_); - - // The version function name - based on the SHA1 - const string checkFuncName - ( - dynCode.codeName() + "_" + context.sha1().str() - ); - - const fileName libPath = dynCode.libPath(); + + // see if library is loaded void* lib = dlLibraryTable::findLibrary(libPath); - // Load library if not already loaded - bool reusing = false; - if (!lib && dlLibraryTable::open(libPath, false)) - { - lib = dlLibraryTable::findLibrary(libPath); - reusing = true; - } - - - // library may have loaded, the version may not be correct + bool reuseLib = false; bool waiting = false; - if (lib) + + if (useCodeProps) { - // Unload library if needed - if (!dlSym(lib, checkFuncName)) + // library may be loaded, but out-of-date + const codeProperties& codeProps = this->dict(); + if (codeProps.modified()) { - reusing = false; - waiting = true; - if (!dlLibraryTable::close(libPath, false)) - { - FatalIOErrorIn - ( - "codedFixedValueFvPatchScalarField::updateLibrary(..)", - context.dict() - ) << "Failed unloading library " - << libPath - << exit(FatalIOError); - } - lib = 0; - } + codeProps.setUnmodified(); - // unload from all processes - reduce(waiting, orOp()); - } - - - // create library - if (!lib) - { - if (useInlineDict) - { - createLibrary(dynCode, context); - } - else - { // Remove instantiation of fvPatchField provided by library redirectPatchFieldPtr_.clear(); - createLibrary(dynCode, context); - } + contextPtr.reset(new dynamicCodeContext(codeDict)); + + // unload code + if (lib) + { + firstTime = false; + reuseLib = false; + lib = 0; + + if (!dlLibraryTable::close(libPath, false)) + { + FatalIOErrorIn + ( + "codedFixedValueFvPatchScalarField::" + "updateLibrary()", + contextPtr().dict() + ) << "Failed unloading library " + << libPath + << exit(FatalIOError); + } + } + } + } + + + // library exists (and was not unloaded) - we can leave now + if (lib) + { + return; + } + + + // Remove instantiation of fvPatchField provided by library + redirectPatchFieldPtr_.clear(); + + if (contextPtr.empty()) + { + contextPtr.reset(new dynamicCodeContext(codeDict)); + } + + // function name serving as version control - based on the SHA1 + const string sentinelName + = dynCode.codeName() + contextPtr().sha1().str(true); + + // avoid compilation (first time only) by loading an existing library + if (firstTime && dlLibraryTable::open(libPath, false)) + { + lib = dlLibraryTable::findLibrary(libPath); + + // verify the loaded version and unload if needed + if (lib) + { + reuseLib = dlSymFound(lib, sentinelName); + if (!reuseLib) + { + lib = 0; + if (!dlLibraryTable::close(libPath, false)) + { + FatalIOErrorIn + ( + "codedFixedValueFvPatchScalarField::updateLibrary()", + contextPtr().dict() + ) << "Failed unloading library " + << libPath + << exit(FatalIOError); + } + } + } + } + + + // really do need to create library + if (!lib) + { if (Pstream::master()) { + createLibrary(dynCode, contextPtr()); + if (!dynCode.wmakeLibso()) { FatalIOErrorIn ( "codedFixedValueFvPatchScalarField::updateLibrary()", - dict_ + contextPtr().dict() ) << "Failed wmake " << libPath << exit(FatalIOError); } @@ -243,33 +262,43 @@ void Foam::codedFixedValueFvPatchScalarField::updateLibrary() FatalIOErrorIn ( "codedFixedValueFvPatchScalarField::updateLibrary()", - dict_ + contextPtr().dict() ) << "Failed loading library " << libPath << exit(FatalIOError); } - - // paranoid - check that signature function is really there lib = dlLibraryTable::findLibrary(libPath); - if (lib) + if (!lib) { - if (!dlSym(lib, checkFuncName)) - { - FatalIOErrorIn - ( - "codedFixedValueFvPatchScalarField::updateLibrary(..)", - dict_ - ) << "Library loaded - but wrong version!" - << libPath - << exit(FatalIOError); - } - lib = 0; + FatalIOErrorIn + ( + "codedFixedValueFvPatchScalarField::" + "updateLibrary()", + contextPtr().dict() + ) << "Failed to load library " << libPath + << exit(FatalIOError); } + +//#if 0 +// Info<<"check " << libPath << " for " << sentinelName << nl; +// // paranoid - check that signature function is really there +// lib = dlLibraryTable::findLibrary(libPath); +// if (!lib || !dlSymFound(lib, sentinelName)) +// { +// FatalIOErrorIn +// ( +// "codedFixedValueFvPatchScalarField::" +// "updateLibrary()", +// contextPtr().dict() +// ) << "Failed to load library with correct signature " +// << libPath +// << exit(FatalIOError); +// } +//#endif } - else if (reusing) + else if (reuseLib) { - Info<< "Reusing library in " << libPath << nl - << " with " << context.sha1().str() << nl; + Info<< "Reusing library in " << libPath << nl; } } @@ -284,7 +313,7 @@ codedFixedValueFvPatchScalarField ) : fixedValueFvPatchField(p, iF), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() {} @@ -300,7 +329,7 @@ codedFixedValueFvPatchScalarField fixedValueFvPatchField(ptf, p, iF, mapper), dict_(ptf.dict_), redirectType_(ptf.redirectType_), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() {} @@ -315,9 +344,9 @@ codedFixedValueFvPatchScalarField fixedValueFvPatchField(p, iF, dict), dict_(dict), redirectType_(dict.lookup("redirectType")), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() { - updateLibrary(); + updateLibrary(true); } @@ -330,7 +359,7 @@ codedFixedValueFvPatchScalarField fixedValueFvPatchField(ptf), dict_(ptf.dict_), redirectType_(ptf.redirectType_), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() {} @@ -344,7 +373,7 @@ codedFixedValueFvPatchScalarField fixedValueFvPatchField(ptf, iF), dict_(ptf.dict_), redirectType_(ptf.redirectType_), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() {} @@ -366,6 +395,18 @@ Foam::codedFixedValueFvPatchScalarField::redirectPatchField() const dictionary dict(is); Info<< "constructing patchField from :" << dict << endl; +// if (fvPatchScalarField::dictionaryConstructorTablePtr_) +// { +// fvPatchScalarField::dictionaryConstructorPtr funcPtr = +// ( +// fvPatchScalarField::dictionaryConstructorTablePtr_-> +// find(redirectType_)() +// ); +// +// Info<< redirectType_ << " FunctionPtr => " +// << long(funcPtr) << endl; +// } + redirectPatchFieldPtr_.set ( fvPatchScalarField::New diff --git a/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchScalarField.H b/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchScalarField.H index 00bdf64ff0..7b0ef5a642 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchScalarField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchScalarField.H @@ -113,19 +113,21 @@ class codedFixedValueFvPatchScalarField const codeProperties& dict() const; - void createLibrary(dynamicCode&, const dynamicCodeContext& dict); + void createLibrary(dynamicCode&, const dynamicCodeContext&) const; - void updateLibrary(); + //- Update library as required + // Use 'firstTime' to alter behaviour + void updateLibrary(bool firstTime=false) const; public: // Static data members //- Name of the C code template to be used - const static word codeTemplateC; + static const word codeTemplateC; //- Name of the H code template to be used - const static word codeTemplateH; + static const word codeTemplateH; //- Runtime type information @@ -217,7 +219,7 @@ public: ); //- Write - virtual void write(Ostream& os) const; + virtual void write(Ostream&) const; };