objectRegistry.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 "objectRegistry.H"
27 #include "Time.H"
28 #include "IOmanip.H"
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
35 }
36 
37 
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 
40 bool Foam::objectRegistry::parentNotTime() const
41 {
42  return (&parent_ != dynamic_cast<const objectRegistry*>(&time_));
43 }
44 
45 
46 void Foam::objectRegistry::readCacheTemporaryObjects() const
47 {
48  if
49  (
50  cacheTemporaryObjectsState_ == 0
51  && time_.controlDict().found("cacheTemporaryObjects")
52  )
53  {
54  cacheTemporaryObjectsState_ = 1;
55 
56  const dictionary& controlDict = time_.controlDict();
57 
58  wordList cacheTemporaryObjects;
59 
60  if (controlDict.isDict("cacheTemporaryObjects"))
61  {
62  if(controlDict.subDict("cacheTemporaryObjects").found(name()))
63  {
64  controlDict.subDict("cacheTemporaryObjects").lookup(name())
65  >> cacheTemporaryObjects;
66  }
67  }
68  else
69  {
70  controlDict.lookup("cacheTemporaryObjects")
71  >> cacheTemporaryObjects;
72  }
73 
74  forAll(cacheTemporaryObjects, i)
75  {
76  cacheTemporaryObjects_.insert
77  (
78  cacheTemporaryObjects[i],
79  {false, false}
80  );
81  }
82  }
83 }
84 
85 
86 void Foam::objectRegistry::deleteCachedObject(regIOobject& cachedOb) const
87 {
88  cachedOb.release();
89  cachedOb.checkOut();
90  cachedOb.rename(cachedOb.name() + "Cached");
91  delete &cachedOb;
92 }
93 
94 
95 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
96 
98 (
99  const Time& t,
100  const label nIoObjects
101 )
102 :
104  (
105  IOobject
106  (
107  string::validate<word>(t.caseName()),
108  t.path(),
109  t,
110  IOobject::NO_READ,
111  IOobject::AUTO_WRITE,
112  false
113  ),
114  true // to flag that this is the top-level regIOobject
115  ),
116  HashTable<regIOobject*>(nIoObjects),
117  time_(t),
118  parent_(t),
119  dbDir_(fileName::null),
120  event_(1),
121  cacheTemporaryObjectsState_(0)
122 {}
123 
124 
126 (
127  const IOobject& io,
128  const fileName& dbDir,
129  const label nIoObjects
130 )
131 :
132  regIOobject(io),
133  HashTable<regIOobject*>(nIoObjects),
134  time_(io.time()),
135  parent_(io.db()),
136  dbDir_(dbDir),
137  event_(1),
138  cacheTemporaryObjectsState_(0)
139 {
141 }
142 
143 
145 (
146  const IOobject& io,
147  const label nIoObjects
148 )
149 :
150  objectRegistry(io, io.db().dbDir()/io.local()/io.name(), nIoObjects)
151 {}
152 
153 
154 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
155 
157 {
158  cacheTemporaryObjects_.clear();
159  cacheTemporaryObjectsState_ = -1;
160 
161  clear();
162 }
163 
164 
165 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
166 
168 (
169  const word& instance,
170  const fileName& local
171 ) const
172 {
173  // Note: can only be called with relative instance since is word type
174  return rootPath()/caseName()/instance/dbDir()/local;
175 }
176 
177 
179 {
180  wordList objectNames(size());
181 
182  label count=0;
183  for (const_iterator iter = cbegin(); iter != cend(); ++iter)
184  {
185  if (iter()->type() == ClassName)
186  {
187  objectNames[count++] = iter.key();
188  }
189  }
190 
191  objectNames.setSize(count);
192 
193  return objectNames;
194 }
195 
196 
198 {
199  wordList sortedLst = toc(ClassName);
200  sort(sortedLst);
201 
202  return sortedLst;
203 }
204 
205 
207 {
208  List<Pair<word>> objectNames(size());
209 
210  label count=0;
211  for (const_iterator iter = cbegin(); iter != cend(); ++iter)
212  {
213  objectNames[count].first() = iter.key();
214  objectNames[count].second() = iter()->type();
215  count++;
216  }
217 
218  return objectNames;
219 }
220 
221 
223 (
224  const word& name,
225  const bool forceCreate
226 ) const
227 {
228  if (forceCreate && !foundObject<objectRegistry>(name))
229  {
230  objectRegistry* fieldsCachePtr = new objectRegistry
231  (
232  IOobject
233  (
234  name,
235  time().constant(),
236  *this,
239  )
240  );
241  fieldsCachePtr->store();
242  }
243  return lookupObject<objectRegistry>(name);
244 }
245 
246 
248 {
249  uint64_t curEvent = event_++;
250 
251  if (event_ == pTraits<uint64_t>::max)
252  {
254  << "Event counter has overflowed!"
255  << abort(FatalError);
256  }
257 
258  return curEvent;
259 }
260 
261 
263 {
264  if (objectRegistry::debug)
265  {
266  Pout<< "objectRegistry::checkIn(regIOobject&) : "
267  << name() << " : checking in " << io.name()
268  << " of type " << io.type()
269  << endl;
270  }
271 
272  const objectRegistry& root = time_;
273 
274  // Delete cached object with the same name as io and if it is in the
275  // cacheTemporaryObjects list
276  HashTable<Pair<bool>>::iterator cacheIter
277  (
278  root.cacheTemporaryObjects_.find(io.name())
279  );
280  if (cacheIter != root.cacheTemporaryObjects_.end())
281  {
282  iterator iter = const_cast<objectRegistry&>(*this).find(io.name());
283 
284  if (iter != end() && iter() != &io && iter()->ownedByRegistry())
285  {
286  if (objectRegistry::debug)
287  {
288  Pout<< "objectRegistry::checkIn(regIOobject&) : "
289  << name() << " : deleting cached object " << iter.key()
290  << endl;
291  }
292 
293  cacheIter().first() = false;
294  deleteCachedObject(*iter());
295  }
296  }
297 
298  return const_cast<objectRegistry&>(*this).insert(io.name(), &io);
299 }
300 
301 
303 {
304  iterator iter = const_cast<objectRegistry&>(*this).find(io.name());
305 
306  if (iter != end())
307  {
308  if (objectRegistry::debug)
309  {
310  Pout<< "objectRegistry::checkOut(regIOobject&) : "
311  << name() << " : checking out " << iter.key()
312  << endl;
313  }
314 
315  if (iter() != &io)
316  {
317  if (objectRegistry::debug)
318  {
320  << name() << " : attempt to checkOut copy of "
321  << iter.key()
322  << endl;
323  }
324 
325  return false;
326  }
327  else
328  {
329  regIOobject* object = iter();
330 
331  bool hasErased = const_cast<objectRegistry&>(*this).erase(iter);
332 
333  if (io.ownedByRegistry())
334  {
335  delete object;
336  }
337 
338  return hasErased;
339  }
340  }
341  else
342  {
343  if (objectRegistry::debug)
344  {
345  Pout<< "objectRegistry::checkOut(regIOobject&) : "
346  << name() << " : could not find " << io.name()
347  << " in registry " << name()
348  << endl;
349  }
350  }
351 
352  return false;
353 }
354 
355 
357 {
358  List<regIOobject*> myObjects(size());
359  label nMyObjects = 0;
360 
361  for (iterator iter = begin(); iter != end(); ++iter)
362  {
363  if (iter()->ownedByRegistry())
364  {
365  myObjects[nMyObjects++] = iter();
366  }
367  }
368 
369  for (label i=0; i < nMyObjects; i++)
370  {
371  checkOut(*myObjects[i]);
372  }
373 }
374 
375 
377 {
378  const objectRegistry& root = time_;
379 
380  root.cacheTemporaryObjects_.insert(name, {false, false});
381 }
382 
383 
385 (
386  const word& name
387 ) const
388 {
389  const objectRegistry& root = time_;
390 
391  return root.cacheTemporaryObjects_.found(name);
392 }
393 
394 
396 (
397  const regIOobject& ob
398 ) const
399 {
400  // If object ob if is in the cacheTemporaryObjects list
401  // and has been cached reset the cached flag
402  HashTable<Pair<bool>>::iterator iter
403  (
404  cacheTemporaryObjects_.find(ob.name())
405  );
406  if (iter != cacheTemporaryObjects_.end())
407  {
408  iter().first() = false;
409  }
410 
411  // Reset the object in the time registry also
412  if (this != &time_)
413  {
414  time_.resetCacheTemporaryObject(ob);
415  }
416 }
417 
418 
420 {
422  {
423  const objectRegistry* orPtr_ =
424  dynamic_cast<const objectRegistry*>(iter());
425 
426  // Protect against re-searching the top-level registry
427  if (orPtr_ && orPtr_ != this)
428  {
429  orPtr_->checkCacheTemporaryObjects();
430  }
431  }
432 
433  const objectRegistry& root = time_;
434 
435  if (root.cacheTemporaryObjects_.empty())
436  {
437  return false;
438  }
439 
440  if (this != &root)
441  {
442  forAllIter
443  (
444  typename HashTable<Pair<bool>>,
445  root.cacheTemporaryObjects_,
446  iter
447  )
448  {
449  if (!iter().second())
450  {
451  Warning
452  << "Could not find temporary object " << iter.key()
453  << " in registry " << name() << nl
454  << "Available temporary objects "
455  << temporaryObjects_
456  << endl;
457  }
458  }
459 
460  cacheTemporaryObjects_.clear();
461  }
462  else
463  {
464  forAllIter
465  (
466  typename HashTable<Pair<bool>>,
467  root.cacheTemporaryObjects_,
468  iter
469  )
470  {
471  iter().second() = false;
472  }
473  }
474 
475  temporaryObjects_.clear();
476 
477  return true;
478 }
479 
480 
481 void Foam::objectRegistry::rename(const word& newName)
482 {
483  regIOobject::rename(newName);
484 
485  // adjust dbDir_ as well
486  string::size_type i = dbDir_.rfind('/');
487 
488  if (i == string::npos)
489  {
490  dbDir_ = newName;
491  }
492  else
493  {
494  dbDir_.replace(i+1, string::npos, newName);
495  }
496 }
497 
498 
500 {
502  {
503  if (iter()->modified())
504  {
505  return true;
506  }
507  }
508 
509  return false;
510 }
511 
512 
514 {
515  dependents_.setSize(size());
516 
517  label count=0;
519  {
520  if (iter()->dependenciesModified())
521  {
522  dependents_[count++] = iter();
523  }
524  }
525  dependents_.setSize(count);
526 
527  return count != 0;
528 }
529 
530 
532 {
533  bool modified = false;
534 
535  for (iterator iter = begin(); iter != end(); ++iter)
536  {
537  if (objectRegistry::debug)
538  {
539  Pout<< "objectRegistry::readModifiedObjects() : "
540  << name() << " : Considering reading object "
541  << iter.key() << endl;
542  }
543 
544  modified = modified || iter()->readIfModified();
545  }
546 
547  return modified;
548 }
549 
550 
552 {
553  bool readOk = true;
554 
555  forAll(dependents_, i)
556  {
557  dependents_[i]->read();
558  }
559 
560  return readOk;
561 }
562 
563 
565 {
566  dependenciesModified();
567 
568  const bool modified = readIfModified();
569 
570  // If any objects have been modified and re-read, read the dependants
571  if (modified)
572  {
574  }
575 }
576 
577 
579 {
581  (
582  sorted()
583  );
584 
585  forAll(sortedObjects, i)
586  {
587  os << " " << setf(ios_base::left)
588  << setw(39) << sortedObjects[i].key()
589  << ' ' << sortedObjects[i]()->type()
590  << endl;
591  }
592 }
593 
594 
596 (
600  const bool write
601 ) const
602 {
603  bool ok = true;
604 
606  {
607  if (objectRegistry::debug)
608  {
609  Pout<< "objectRegistry::write() : "
610  << name() << " : Considering writing object "
611  << iter.key()
612  << " of type " << iter()->type()
613  << " with writeOpt " << iter()->writeOpt()
614  << " to file " << iter()->objectPath()
615  << endl;
616  }
617 
618  if (iter()->writeOpt() != NO_WRITE)
619  {
620  ok = iter()->writeObject(fmt, ver, cmp, write) && ok;
621  }
622  }
623 
624  return ok;
625 }
626 
627 
628 // ************************************************************************* //
Istream and Ostream manipulators taking arguments.
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:474
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
An STL-conforming hash table.
Definition: HashTable.H:127
List< word > sortedToc() const
Return the table of contents as a sorted list.
Definition: HashTable.C:242
bool erase(const iterator &)
Erase a hashedEntry specified by given iterator.
Definition: HashTable.C:445
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:167
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
writeOption & writeOpt() const
Definition: IOobject.H:367
const word & name() const
Return name.
Definition: IOobject.H:307
Version number type.
Definition: IOstream.H:97
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:87
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:194
void setSize(const label)
Reset size of List.
Definition: List.C:281
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
T & first()
Return the first element of the list.
Definition: UListI.H:114
A class for handling file names.
Definition: fileName.H:82
Registry of regIOobjects.
virtual bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp, const bool write) const
Write the objects.
wordList toc() const
Return the list of names of the IOobjects of given type.
const objectRegistry & subRegistry(const word &name, const bool forceCreate=false) const
Lookup and return a const sub-objectRegistry. Optionally create.
void printToc(Ostream &os) const
Print the list of object names and their type.
bool temporaryObjectCached(const word &name) const
Return true if given name is in the cacheTemporaryObjects set.
virtual bool modified() const
Return true if any of the object's files have been modified.
objectRegistry(const Time &db, const label nIoObjects=128)
Construct the time objectRegistry given an initial estimate.
virtual bool dependenciesModified() const
Cache pointers to objects who's dependencies have been modified.
void cacheTemporary(const word &name) const
Add the given name to the cacheTemporaryObjects set.
virtual ~objectRegistry()
Destructor.
bool checkCacheTemporaryObjects() const
Check that all objects in the cacheTemporaryObjects set.
List< Pair< word > > tocTypes() const
Return the list of names and types of IOobjects.
uint64_t getEvent() const
Return new event number.
virtual bool readIfModified()
Read object if modified.
fileName path() const
Return complete path.
Definition: regIOobject.C:175
void clear()
Remove all regIOobject owned by the registry.
void resetCacheTemporaryObject(const regIOobject &ob) const
Reset the cache state of the given object.
void readModifiedObjects()
Read the objects that have been modified.
virtual void rename(const word &newName)
Rename.
virtual bool read()
Read dependent objects.
Traits class for primitives.
Definition: pTraits.H:53
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:55
bool ownedByRegistry() const
Is this object owned by the registry?
Definition: regIOobjectI.H:34
bool checkOut()
Remove object from registry.
Definition: regIOobject.C:217
virtual void rename(const word &newName)
Rename.
Definition: regIOobject.C:393
void store()
Transfer ownership of this object to its registry.
Definition: regIOobjectI.H:40
bool checkIn()
Add object to registry.
Definition: regIOobject.C:181
A class for handling character strings derived from std::string.
Definition: string.H:79
string & replace(const string &oldStr, const string &newStr, size_type start=0)
In this string replace first occurrence of sub-string oldStr.
Definition: string.C:64
A class for handling words, derived from string.
Definition: word.H:63
#define ClassName(TypeNameString)
Add typeName information from argument a TypeNameString to a class.
Definition: className.H:71
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
tUEqn clear()
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionSet time
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
Namespace for OpenFOAM.
List< word > wordList
A List of words.
Definition: fileName.H:54
Smanip< ios_base::fmtflags > setf(const ios_base::fmtflags flags)
Definition: IOmanip.H:164
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
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
errorManip< error > abort(error &err)
Definition: errorManip.H:131
labelList second(const UList< labelPair > &p)
Definition: patchToPatch.C:49
void sort(UList< T > &)
Definition: UList.C:115
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
error FatalError
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
static const char nl
Definition: Ostream.H:297
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
messageStream Warning
runTime controlDict().lookup("adjustTimeStep") >> adjustTimeStep
thermo validate(args.executable(), "h")
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:112