ENH: new encapsulation: dynamicCode, dynamicCodeContext

- improve loading/unloading characteristics for codedFixedValue
  but still needs work
This commit is contained in:
Mark Olesen
2011-02-24 17:14:59 +01:00
parent 51399bbbd1
commit 74bc658fe9
11 changed files with 946 additions and 731 deletions

View File

@ -28,10 +28,9 @@ License
#include "IStringStream.H"
#include "OStringStream.H"
#include "IOstreams.H"
#include "SHA1Digest.H"
#include "OSHA1stream.H"
#include "codeStreamTools.H"
#include "stringOps.H"
#include "dynamicCode.H"
#include "dynamicCodeContext.H"
#include "dlLibraryTable.H"
#include "OSspecific.H"
#include "Time.H"
@ -71,7 +70,7 @@ bool Foam::functionEntries::codeStream::execute
Istream& is
)
{
codeStreamTools::checkSecurity
dynamicCode::checkSecurity
(
"functionEntries::codeStream::execute(..)",
parentDict
@ -81,54 +80,23 @@ bool Foam::functionEntries::codeStream::execute
// must reference parent for stringOps::expand to work nicely
dictionary codeDict("#codeStream", parentDict, is);
// get code, codeInclude, codeOptions
dynamicCodeContext context(codeDict);
// Read three sections of code.
// Remove any leading whitespace - necessary for compilation options,
// convenience for includes and body.
// "codeInclude" is optional
string codeInclude;
if (codeDict.found("codeInclude"))
{
codeInclude = stringOps::trim(codeDict["codeInclude"]);
stringOps::inplaceExpand(codeInclude, codeDict);
}
// "codeOptions" is optional
string codeOptions;
if (codeDict.found("codeOptions"))
{
codeOptions = stringOps::trim(codeDict["codeOptions"]);
stringOps::inplaceExpand(codeOptions, codeDict);
}
// "code" is mandatory
string code = stringOps::trim(codeDict["code"]);
stringOps::inplaceExpand(code, codeDict);
// Create SHA1 digest from the contents
SHA1Digest sha;
{
OSHA1stream os;
os << codeInclude << codeOptions << code;
sha = os.digest();
}
// codeName = prefix + sha1
const fileName codeName = "codeStream_" + sha.str();
// write code into _SHA1 subdir
const fileName codePath = codeStreamTools::codePath("_" + sha.str());
// write library into platforms/$WM_OPTIONS/lib subdir
const fileName libPath = codeStreamTools::libPath(codeName);
// codeName: prefix_ + sha1
// codeDir : _<sha1>
dynamicCode dynCode
(
"codeStream_" + context.sha1().str(),
"_" + context.sha1().str()
);
// Load library if not already loaded
// Version information is encoded in the libPath (encoded with the SHA1)
const fileName libPath = dynCode.libPath();
void* lib = dlLibraryTable::findLibrary(libPath);
// try to load if not already loaded
if (!lib && dlLibraryTable::open(libPath, false))
{
lib = dlLibraryTable::findLibrary(libPath);
@ -139,76 +107,54 @@ bool Foam::functionEntries::codeStream::execute
{
if (Pstream::master())
{
if (!codeStreamTools::upToDate(codePath, sha))
if (!dynCode.upToDate(context))
{
Info<< "Creating new library in " << libPath << endl;
Info<< "Creating new library in "
<< dynCode.libPath() << endl;
const fileName fileCsrc
(
codeStreamTools::findTemplate
(
codeTemplateC
)
);
// filter C template
dynCode.addFilterFile(codeTemplateC);
// not found!
if (fileCsrc.empty())
{
FatalIOErrorIn
(
"functionEntries::codeStream::execute(..)",
parentDict
) << "Could not find the code template: "
<< codeTemplateC << nl
<< codeStreamTools::searchedLocations()
<< exit(FatalIOError);
}
List<codeStreamTools::fileAndVars> copyFiles(1);
copyFiles[0].file() = fileCsrc;
copyFiles[0].set("codeInclude", codeInclude);
copyFiles[0].set("code", code);
copyFiles[0].set("SHA1sum", sha.str());
List<codeStreamTools::fileAndContent> filesContents(2);
// filter with this context
dynCode.setFilterContext(context);
// Write Make/files
filesContents[0].first() = "Make/files";
filesContents[0].second() =
dynCode.addCreateFile
(
"Make/files",
codeTemplateC + "\n\n"
+ codeStreamTools::libTarget(codeName);
+ dynCode.libTarget()
);
// Write Make/options
filesContents[1].first() = "Make/options";
filesContents[1].second() =
dynCode.addCreateFile
(
"Make/options",
"EXE_INC = -g \\\n"
+ codeOptions
+ "\n\nLIB_LIBS =";
+ context.options()
+ "\n\nLIB_LIBS ="
);
codeStreamTools writer(codeName, copyFiles, filesContents);
if (!writer.copyFilesContents(codePath))
if (!dynCode.copyFilesContents())
{
FatalIOErrorIn
(
"functionEntries::codeStream::execute(..)",
parentDict
) << "Failed writing " <<nl
<< copyFiles << endl
<< filesContents
) << "Failed writing " << nl
// << copyFiles << endl
// << filesContents
<< exit(FatalIOError);
}
}
const Foam::string wmakeCmd("wmake libso " + codePath);
Info<< "Invoking " << wmakeCmd << endl;
if (Foam::system(wmakeCmd))
if (!dynCode.wmakeLibso())
{
FatalIOErrorIn
(
"functionEntries::codeStream::execute(..)",
parentDict
) << "Failed " << wmakeCmd
) << "Failed wmake " << libPath
<< exit(FatalIOError);
}
}
@ -239,16 +185,17 @@ bool Foam::functionEntries::codeStream::execute
void (*function)(const dictionary&, Ostream&);
function = reinterpret_cast<void(*)(const dictionary&, Ostream&)>
(
dlSym(lib, codeName)
dlSym(lib, dynCode.codeName())
);
if (!function)
{
FatalIOErrorIn
(
"functionEntries::codeStream::execute(..)",
parentDict
) << "Failed looking up symbol " << codeName
) << "Failed looking up symbol " << dynCode.codeName()
<< " in library " << lib << exit(FatalIOError);
}