diff --git a/doc/changes/dynamicCode.org b/doc/changes/dynamicCode.org index 1cd3d3338a5746a447d2107e000690e78042b87b..9ea400ef4b0b2d15e7af0a4945ed3742800fc472 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 50a47e1b1ae4acd35024f4a3fab147d59bfd75ab..35ff81f47667f83e528a78b0de97d38db3036425 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 da2b6379791008e9e696181cbc82aa87924c86f4..92a6b444f128d6d1efe8d7ff8cdfd2d570d0b7b2 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 + _<sha1> // codeDir : _<sha1> 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>()); + bool waiting = true; + reduce(waiting, orOp<bool>()); 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<void(*)(const dictionary&, Ostream&)> + // Find the function handle in the library + void (*function)(Ostream&, const dictionary&); + function = reinterpret_cast<void(*)(Ostream&, const dictionary&)> ( 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 e04bdceaa4f163b6ed0b8773d1c67e2cf2d49905..10e3262ca1bf9066d109a3fd63a0a1c0dcfd879e 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 b4c52afbb039e3bd9c0866c39e321124daaac97b..2493ad8d1686d51d271a00fcbe02b0aad03c64f4 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<string>& 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::fileName> -Foam::dynamicCode::resolveTemplates(const UList<fileName>& names) +bool Foam::dynamicCode::resolveTemplates +( + const UList<fileName>& templateNames, + DynamicList<fileName>& resolvedFiles, + DynamicList<fileName>& badFiles +) { // try to get template from FOAM_CODESTREAM_TEMPLATES const fileName templateDir(Foam::getEnv(codeTemplateEnvName)); - DynamicList<fileName> badFiles(names.size()); - List<fileName> 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,90 +154,194 @@ Foam::dynamicCode::resolveTemplates(const UList<fileName>& 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) + { + os << "/* dynamicCode:\n * SHA1 = "; + os.writeQuoted(filterVars_["SHA1sum"], false) << "\n */\n"; + } + + 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::resolveTemplates(..)" - ) << "Could not find the code template(s): " - << badFiles << nl - << "Under the $" << codeTemplateDirName - << " directory or via via the ~OpenFOAM/" - << codeTemplateDirName << " expansion" - << exit(FatalError); + ( + "dynamicCode::createMakeFiles()" + " const" + ) << "Failed writing " << dstFile + << exit(FatalError); } - return resolved; + writeCommentSHA1(os); + + // Write compile files + forAll(compileFiles_, fileI) + { + os.writeQuoted(compileFiles_[fileI], false) << nl; + } + + os << nl + << libTargetRoot << codeName_.c_str() << nl; + + return true; } -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // +bool Foam::dynamicCode::createMakeOptions() const +{ + // Create Make/options + if (compileFiles_.empty() || makeOptions_.empty()) + { + return false; + } -Foam::dynamicCode::dynamicCode(const word& codeName) -: - codeName_(codeName), - codeDirName_(codeName) + 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 { - filterVars_.set("typeName", codeName_); - filterVars_.set("SHA1sum", SHA1Digest().str()); + 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, 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_; + } -// Foam::dynamicCode::dynamicCode(const dynamicCode& dc) -// : -// codeName_(dc.codeName_), -// copyFiles_(dc.copyFiles_), -// filesContents_(dc.filesContents_) -// {} + clear(); +} // * * * * * * * * * * * * * * * 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::addCreateFile +void Foam::dynamicCode::reset ( - const fileName& name, - const string& contents + const dynamicCodeContext& context ) { - createFiles_.append(fileAndContent(name, contents)); + 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::addFilterFile +void Foam::dynamicCode::addCreateFile ( - const fileName& name + const fileName& name, + const string& contents ) { - filterFiles_.append(name); + createFiles_.append(fileAndContent(name, contents)); } @@ -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" - ); -} - - -Foam::string Foam::dynamicCode::libTarget() const -{ - return "LIB = $(PWD)/../platforms/$(WM_OPTIONS)/lib/lib" + codeName_; -} - - + if (verbose) + { + Info<< "Creating new library in " << this->libPath() << endl; + } -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<fileName> resolvedFiles = resolveTemplates(filterFiles_); + const label nFiles = compileFiles_.size() + copyFiles_.size(); + + DynamicList<fileName> resolvedFiles(nFiles); + DynamicList<fileName> 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 d1224861561a0a559304c0dd518dd3e2f0ac692b..af7f996c08d34ca33d352644cd6f7923ddc57c8b 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<string> filterVars_; + //- Files to copy and filter + DynamicList<fileName> compileFiles_; + + //- Files to copy and filter + DynamicList<fileName> copyFiles_; //- Direct contents for files DynamicList<fileAndContent> createFiles_; - //- Files to copy and filter - DynamicList<fileName> filterFiles_; + //- Variables to use during filtering + HashTable<string> 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<string>& mapping - ) const; + ); //- Resolve code-templates via the codeTemplateEnvName // alternatively in the codeTemplateDirName via Foam::findEtcFile - static List<fileName> resolveTemplates + static bool resolveTemplates ( - const UList<fileName>& names + const UList<fileName>& templateNames, + DynamicList<fileName>& resolvedFiles, + DynamicList<fileName>& 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\<codeName\>.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 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); + 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); //- Define filter variables for code, codeInclude, SHA1sum void setFilterContext(const dynamicCodeContext&); //- Define a filter variable - void setFilterVariable(const word& key, const string& value); - - - //- 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; + void setFilterVariable(const word& key, const std::string& value); - //- The library target path for Make/files - string libTarget() const; + //- Define contents for Make/options + void setMakeOptions(const std::string& content); - //- 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 a467943f6599a138dbe1fbbb01619c0c9c01425f..8175f1b5ed6793a50fe9c79ac5060fe4ebaf3df1 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 - ( - "Make/files", - codeTemplateC + "\n\n" - + dynCode.libTarget() - ); + // copy filtered H template + dynCode.addCopyFile(codeTemplateH); - // Make/options - dynCode.addCreateFile + // define Make/options + dynCode.setMakeOptions ( - "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<dynamicCodeContext> 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)) + bool reuseLib = false; + bool waiting = false; + + if (useCodeProps) { - lib = dlLibraryTable::findLibrary(libPath); - reusing = true; + // library may be loaded, but out-of-date + const codeProperties& codeProps = this->dict(); + if (codeProps.modified()) + { + codeProps.setUnmodified(); + + // Remove instantiation of fvPatchField provided by library + redirectPatchFieldPtr_.clear(); + + 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 may have loaded, the version may not be correct - bool waiting = false; + // library exists (and was not unloaded) - we can leave now if (lib) { - // Unload library if needed - if (!dlSym(lib, checkFuncName)) + 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) { - reusing = false; - waiting = true; - if (!dlLibraryTable::close(libPath, false)) + reuseLib = dlSymFound(lib, sentinelName); + if (!reuseLib) { - FatalIOErrorIn - ( - "codedFixedValueFvPatchScalarField::updateLibrary(..)", - context.dict() - ) << "Failed unloading library " - << libPath - << exit(FatalIOError); + lib = 0; + if (!dlLibraryTable::close(libPath, false)) + { + FatalIOErrorIn + ( + "codedFixedValueFvPatchScalarField::updateLibrary()", + contextPtr().dict() + ) << "Failed unloading library " + << libPath + << exit(FatalIOError); + } } - lib = 0; } - - // unload from all processes - reduce(waiting, orOp<bool>()); } - // create library + // really do need to create library if (!lib) { - if (useInlineDict) - { - createLibrary(dynCode, context); - } - else - { - // Remove instantiation of fvPatchField provided by library - redirectPatchFieldPtr_.clear(); - createLibrary(dynCode, context); - } - 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<scalar>(p, iF), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() {} @@ -300,7 +329,7 @@ codedFixedValueFvPatchScalarField fixedValueFvPatchField<scalar>(ptf, p, iF, mapper), dict_(ptf.dict_), redirectType_(ptf.redirectType_), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() {} @@ -315,9 +344,9 @@ codedFixedValueFvPatchScalarField fixedValueFvPatchField<scalar>(p, iF, dict), dict_(dict), redirectType_(dict.lookup("redirectType")), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() { - updateLibrary(); + updateLibrary(true); } @@ -330,7 +359,7 @@ codedFixedValueFvPatchScalarField fixedValueFvPatchField<scalar>(ptf), dict_(ptf.dict_), redirectType_(ptf.redirectType_), - redirectPatchFieldPtr_(NULL) + redirectPatchFieldPtr_() {} @@ -344,7 +373,7 @@ codedFixedValueFvPatchScalarField fixedValueFvPatchField<scalar>(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 00bdf64ff03df9a04397260e41d1ba9bfde3c681..7b0ef5a6420d2f8c683caeb2d318c2db44221be3 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; };