codeStream.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "codeStream.H"
27 #include "dynamicCode.H"
28 #include "Time.H"
29 #include "OSspecific.H"
30 #include "PstreamReduceOps.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 namespace functionEntries
39 {
41 
43 
45  (
47  codeStream,
48  execute,
49  primitiveEntryIstream
50  );
51 }
52 }
53 
54 
56 (
57  {"code", "codeInclude", "localCode"}
58 );
59 
61 (
62  {"dict", word::null, word::null}
63 );
64 
66 (
67  "codeStreamOptions"
68 );
69 
71 {
72  "codeStreamTemplate.C"
73 };
74 
75 
76 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
77 
78 bool Foam::functionEntries::codeStream::masterOnlyRead
79 (
80  const word& typeName,
81  const dictionary& dict
82 )
83 {
84  const dictionary& topDict = dict.topDict();
85 
86  if (debug)
87  {
88  Pout<< typeName << " : dictionary:" << dict.name()
89  << " master-only-reading:" << topDict.global()
90  << endl;
91  }
92 
93  return topDict.global();
94 }
95 
96 
97 Foam::string Foam::functionEntries::codeStream::codeString
98 (
99  const word& typeName,
100  const word& templateFunctionName,
101  const label index,
102  const dictionary& contextDict,
103  Istream& is
104 )
105 {
106  // Construct code string for codeStream using the context dictionary for
107  // string expansion and variable substitution
108  const dictionary codeDict(typeName, contextDict, is);
109 
110  if (codeDict.found("codeInclude"))
111  {
113  << "codeInclude entry not supported within #codeBlock, "
114  "use #codeInclude instead."
115  << endl;
116  }
117 
118  return
119  (
120  templateFunctionName + '(' + Foam::name(index) + ")\n"
121  "{\n"
122  " #line " + Foam::name(codeDict.lookup("code").lineNumber())
123  + " \"" + codeDict.name() + "\"\n"
124  + codeDict.lookup<verbatimString>("code")
125  + "\n}\n\n"
126  );
127 }
128 
129 
130 Foam::string Foam::functionEntries::codeStream::codeString
131 (
132  const label index,
133  const dictionary& contextDict,
134  Istream& is
135 )
136 {
137  return codeString
138  (
139  typeName,
140  "CODE_BLOCK_STREAM_FUNCTION",
141  index,
142  contextDict,
143  is
144  );
145 }
146 
147 
148 void* Foam::functionEntries::codeStream::compile
149 (
150  const word& typeName,
151  const dictionary& contextDict,
152  const dictionary& codeDict,
153  const word& codeOptions,
154  const wordList& compileFiles,
155  word& codeName
156 )
157 {
158  // Get code, codeInclude, ...
159  // codeName: codeStream + _<sha1>
160  // codeDir : _<sha1>
161  dynamicCode dynCode
162  (
163  contextDict,
164  codeDict,
165  typeName.remove('#'),
166  word::null,
167  codeKeys,
168  codeDictVars,
169  codeOptions,
170  compileFiles,
172  );
173 
174  // Load library if not already loaded
175  // Version information is encoded in the libPath (encoded with the SHA1)
176  const fileName libPath = dynCode.libPath();
177 
178  // See if library is loaded
179  void* lib = libs.findLibrary(libPath);
180 
181  if (debug && !lib)
182  {
183  Info<< "Using " << typeName << " with " << libPath << endl;
184  }
185 
186  // Nothing loaded
187  // avoid compilation if possible by loading an existing library
188  if (!lib)
189  {
190  lib = dynCode.loadLibrary(libPath);
191  }
192 
193  // Create library if required and load
194  if (!lib)
195  {
196  dynCode.createLibrary
197  (
198  contextDict,
199  masterOnlyRead(typeName, contextDict)
200  );
201 
202  lib = dynCode.loadLibrary(libPath);
203  }
204 
205  if (!lib)
206  {
207  FatalIOErrorInFunction(contextDict)
208  << "Failed loading library " << libPath << nl
209  << "Did you add all libraries to the 'libs' entry"
210  << " in system/controlDict?"
211  << exit(FatalIOError);
212  }
213 
214  bool allHaveLib = lib;
215  if (!masterOnlyRead(typeName, contextDict))
216  {
217  reduce(allHaveLib, andOp<bool>());
218  }
219 
220  if (!allHaveLib)
221  {
222  FatalIOErrorInFunction(contextDict)
223  << "Failed loading library " << libPath
224  << " on some processors."
225  << exit(FatalIOError);
226  }
227 
228  codeName = dynCode.codeSha1Name();
229 
230  return lib;
231 }
232 
233 
234 Foam::functionEntries::codeStream::streamingFunctionType
235 Foam::functionEntries::codeStream::getFunction
236 (
237  const dictionary& contextDict,
238  const dictionary& codeDict
239 )
240 {
241  word codeName;
242  void* lib = compile
243  (
244  typeName,
245  contextDict,
246  codeDict,
247  codeOptions,
248  compileFiles,
249  codeName
250  );
251 
252  // Find the function handle in the library
253  const streamingFunctionType function =
254  reinterpret_cast<streamingFunctionType>
255  (
256  dlSym(lib, codeName)
257  );
258 
259  if (!function)
260  {
261  FatalIOErrorInFunction(contextDict)
262  << "Failed looking up symbol " << codeName
263  << " in library " << lib << exit(FatalIOError);
264  }
265 
266  return function;
267 }
268 
269 
270 Foam::OTstream Foam::functionEntries::codeStream::resultStream
271 (
272  const dictionary& contextDict,
273  Istream& is
274 )
275 {
276  if (debug)
277  {
278  Info<< "Using " << typeName << " at line " << is.lineNumber()
279  << " in file " << contextDict.name() << endl;
280  }
281 
282  // Construct codeDict for codeStream using the context dictionary
283  // for string expansion and variable substitution
284  const dictionary codeDict(typeName, contextDict, is);
285 
286  // Compile and link the code library and get the function pointer
287  const streamingFunctionType function = getFunction(contextDict, codeDict);
288 
289  // Use function to write stream
290  OTstream ots(is.name(), is.format());
291  ots.lineNumber() = is.lineNumber();
292  (*function)(ots, contextDict);
293 
294  // Return the OTstream containing the results of the code execution
295  return ots;
296 }
297 
298 
299 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
300 
302 (
303  const functionName& functionType,
304  const label lineNumber,
305  const dictionary& dict
306 )
307 :
308  functionEntry(functionType, lineNumber, dict)
309 {}
310 
311 
313 (
314  const label lineNumber,
315  const dictionary& parentDict,
316  Istream& is
317 )
318 :
319  functionEntry(typeName, lineNumber, parentDict)
320 {}
321 
322 
323 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
324 
326 (
327  dictionary& contextDict,
328  Istream& is
329 )
330 {
331  return insert(contextDict, resultStream(contextDict, is));
332 }
333 
334 
336 (
337  const dictionary& contextDict,
338  primitiveEntry& contextEntry,
339  Istream& is
340 )
341 {
342  return insert(contextDict, contextEntry, resultStream(contextDict, is));
343 }
344 
345 
346 // ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Inter-processor communication reduction functions.
Macros for easy insertion into member function selection tables.
Macros for easy insertion into run-time selection tables.
bool global() const
Return global state.
Definition: IOstream.H:438
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
static const List< word > & null()
Return a null List.
Definition: ListI.H:118
Output token stream.
Definition: OTstream.H:56
const fileName & name() const
Return the dictionary name.
Definition: dictionary.H:111
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
const dictionary & topDict() const
Return the top of the tree.
Definition: dictionary.C:341
void * findLibrary(const fileName &libName)
Find the handle of the named library.
Compiles and executes C++ OpenFOAM code string expressions.
Definition: codeStream.H:214
static const word codeOptions
Name of the code options file to be used.
Definition: codeStream.H:286
static const wordList codeKeys
Keywords associated with source code.
Definition: codeStream.H:280
codeStream(const functionName &, const label lineNumber, const dictionary &)
Construct from function type and parent dictionary.
Definition: codeStream.C:302
static const wordList compileFiles
Name of the C code template to be used.
Definition: codeStream.H:289
static const wordList codeDictVars
Name of the dictionary variables in the source code.
Definition: codeStream.H:283
virtual bool execute(dictionary &contextDict, Istream &)
Expand the functionEntry into the contextDict.
Definition: codeStream.C:326
A functionEntry causes entries to be added/manipulated on the specified dictionary given an input str...
Definition: functionEntry.H:66
A functionName is a word starting with '#'.
Definition: functionName.H:60
A keyword and a list of tokens is a 'primitiveEntry'. An primitiveEntry can be read,...
const dictionary & dict() const
This entry is not a dictionary,.
A class for handling character strings derived from std::string.
Definition: string.H:79
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
A class for handling words, derived from string.
Definition: word.H:63
static const word null
An empty word.
Definition: word.H:78
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
defineFunctionTypeNameAndDebug(includeFvConstraintEntry, 0)
addToMemberFunctionSelectionTable(functionEntry, calcEntry, execute, primitiveEntryIstream)
addToRunTimeSelectionTable(functionEntry, includeFvConstraintEntry, dictionary)
void insert(const scalar, DynamicList< floatScalar > &)
Append scalar to given DynamicList.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dlLibraryTable libs
Table of loaded dynamic libraries.
List< word > wordList
A List of words.
Definition: fileName.H:54
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
messageStream Info
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
IOerror FatalIOError
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
void * dlSym(void *handle, const std::string &symbol)
Lookup a symbol in a dlopened library using handle to library.
Definition: POSIX.C:1276
static const char nl
Definition: Ostream.H:297
dictionary dict