1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011-2011 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "codeStream.H"
27 #include "addToMemberFunctionSelectionTable.H"
28 #include "IStringStream.H"
29 #include "OStringStream.H"
30 #include "IOstreams.H"
31 #include "stringOps.H"
32 #include "dynamicCode.H"
33 #include "dynamicCodeContext.H"
34 #include "dlLibraryTable.H"
35 #include "OSspecific.H"
37 #include "PstreamReduceOps.H"
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 namespace functionEntries
47 defineTypeNameAndDebug(codeStream, 0);
49 addToMemberFunctionSelectionTable
61 const Foam::word Foam::functionEntries::codeStream::codeTemplateC
62 = "codeStreamTemplate.C";
65 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
67 const Foam::dictionary& Foam::functionEntries::codeStream::topDict
69 const dictionary& dict
72 const dictionary& p = dict.parent();
74 if (&p != &dict && !p.name().empty())
85 Foam::dlLibraryTable& Foam::functionEntries::codeStream::libs
87 const dictionary& dict
90 const IOdictionary& d = static_cast<const IOdictionary&>(topDict(dict));
91 return const_cast<Time&>(d.time()).libs();
95 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
97 bool Foam::functionEntries::codeStream::execute
99 const dictionary& parentDict,
100 primitiveEntry& entry,
104 Info<< "Using #codeStream at line " << is.lineNumber()
105 << " in file " << parentDict.name() << endl;
107 dynamicCode::checkSecurity
109 "functionEntries::codeStream::execute(..)",
113 // get code dictionary
114 // must reference parent for stringOps::expand to work nicely
115 dictionary codeDict("#codeStream", parentDict, is);
117 // get code, codeInclude, codeOptions
118 dynamicCodeContext context(codeDict);
120 // codeName: codeStream + _<sha1>
124 "codeStream" + context.sha1().str(true),
125 context.sha1().str(true)
128 // Load library if not already loaded
129 // Version information is encoded in the libPath (encoded with the SHA1)
130 const fileName libPath = dynCode.libPath();
132 // see if library is loaded
134 if (isA<IOdictionary>(topDict(parentDict)))
136 lib = libs(parentDict).findLibrary(libPath);
141 Info<< "Using #codeStream with " << libPath << endl;
146 // avoid compilation if possible by loading an existing library
149 if (isA<IOdictionary>(topDict(parentDict)))
151 // Cached access to dl libs. Guarantees clean up upon destruction
153 dlLibraryTable& dlLibs = libs(parentDict);
154 if (dlLibs.open(libPath, false))
156 lib = dlLibs.findLibrary(libPath);
161 // Uncached opening of libPath
162 lib = dlOpen(libPath);
167 // create library if required
170 bool create = Pstream::master();
174 if (!dynCode.upToDate(context))
176 // filter with this context
177 dynCode.reset(context);
179 // compile filtered C template
180 dynCode.addCompileFile(codeTemplateC);
182 // define Make/options
183 dynCode.setMakeOptions
187 + "\n\nLIB_LIBS = \\\n"
192 if (!dynCode.copyOrCreateFiles(true))
196 "functionEntries::codeStream::execute(..)",
198 ) << "Failed writing files for" << nl
199 << dynCode.libRelPath() << nl
200 << exit(FatalIOError);
204 if (!dynCode.wmakeLibso())
208 "functionEntries::codeStream::execute(..)",
210 ) << "Failed wmake " << dynCode.libRelPath() << nl
211 << exit(FatalIOError);
215 // all processes must wait for compile to finish
216 reduce(create, orOp<bool>());
218 if (isA<IOdictionary>(topDict(parentDict)))
220 // Cached access to dl libs. Guarantees clean up upon destruction
222 dlLibraryTable& dlLibs = libs(parentDict);
223 if (!dlLibs.open(libPath, false))
227 "functionEntries::codeStream::execute(..)",
229 ) << "Failed loading library " << libPath << nl
230 << "Did you add all libraries to the 'libs' entry"
231 << " in system/controlDict?"
232 << exit(FatalIOError);
235 lib = dlLibs.findLibrary(libPath);
239 // Uncached opening of libPath
240 lib = dlOpen(libPath);
245 // Find the function handle in the library
246 streamingFunctionType function =
247 reinterpret_cast<streamingFunctionType>
249 dlSym(lib, dynCode.codeName())
257 "functionEntries::codeStream::execute(..)",
259 ) << "Failed looking up symbol " << dynCode.codeName()
260 << " in library " << lib << exit(FatalIOError);
263 // use function to write stream
264 OStringStream os(is.format());
265 (*function)(os, parentDict);
267 // get the entry from this stream
268 IStringStream resultStream(os.str());
269 entry.read(parentDict, resultStream);
275 // ************************************************************************* //