objectRegistry.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2019 OpenFOAM Foundation
9  Copyright (C) 2015-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "objectRegistry.H"
30 #include "Time.H"
31 #include "predicates.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37  defineTypeNameAndDebug(objectRegistry, 0);
38 }
39 
40 
41 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45 
46 // Templated implementation for erase() with iterator range.
47 // Prefer not to expose directly.
48 template<class InputIter>
49 static label eraseImpl(objectRegistry& obr, InputIter first, InputIter last)
50 {
51  label changed = 0;
52 
53  for
54  (
55  const label nTotal = obr.size();
56  changed < nTotal && first != last; // Terminate early
57  ++first
58  )
59  {
60  if (obr.erase(*first))
61  {
62  ++changed;
63  }
64  }
65 
66  return changed;
67 }
68 
69 } // End namespace Foam
70 
71 
72 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
73 
74 bool Foam::objectRegistry::parentNotTime() const noexcept
75 {
76  return (&parent_ != static_cast<const objectRegistry*>(&time_));
77 }
78 
79 
80 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
81 
82 Foam::objectRegistry::objectRegistry
83 (
84  const Time& t,
85  const label initialCapacity
86 )
87 :
89  (
90  IOobject
91  (
92  word::validate(t.caseName()),
93  t.path(),
94  t,
95  IOobjectOption::NO_READ,
96  IOobjectOption::AUTO_WRITE,
97  IOobjectOption::NO_REGISTER
98  ),
99  true // to flag that this is the top-level regIOobject
100  ),
101  HashTable<regIOobject*>(initialCapacity),
102  time_(t),
103  parent_(t),
104  dbDir_(name()),
105  event_(1),
106  cacheTemporaryObjectsActive_(false),
107  cacheTemporaryObjects_(0),
108  temporaryObjects_(0)
109 {}
110 
111 
112 Foam::objectRegistry::objectRegistry
113 (
114  const IOobject& io,
115  const label initialCapacity
116 )
117 :
118  regIOobject(io),
119  HashTable<regIOobject*>(initialCapacity),
120  time_(io.time()),
121  parent_(io.db()),
122  dbDir_(parent_.dbDir()/local()/name()),
123  event_(1),
124  cacheTemporaryObjectsActive_(false),
125  cacheTemporaryObjects_(0),
126  temporaryObjects_(0)
127 {
128  writeOpt(IOobjectOption::AUTO_WRITE);
129 }
130 
131 
132 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
133 
135 {
137 }
138 
139 
140 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
143 {
144  return (this == &static_cast<const objectRegistry&>(time_));
145 }
146 
149 {
150  return classesImpl(*this, predicates::always());
151 }
152 
153 
154 Foam::label Foam::objectRegistry::count(const char* clsName) const
155 {
156  // No nullptr check - only called with string literals
157  return count(static_cast<word>(clsName));
158 }
159 
162 {
164 }
165 
168 {
170 }
171 
172 
173 Foam::wordList Foam::objectRegistry::names(const char* clsName) const
174 {
175  // No nullptr check - only called with string literals
176  return names(static_cast<word>(clsName));
177 }
178 
179 
180 Foam::wordList Foam::objectRegistry::sortedNames(const char* clsName) const
181 {
182  // No nullptr check - only called with string literals
183  return sortedNames(static_cast<word>(clsName));
184 }
185 
186 
188 (
189  const word& name,
190  const bool forceCreate,
191  const bool recursive
192 ) const
193 {
194  if (forceCreate && !foundObject<objectRegistry>(name, recursive))
195  {
196  objectRegistry* subObr = new objectRegistry
197  (
198  IOobject
199  (
200  name,
201  time().constant(),
202  *this,
206  )
207  );
208  subObr->store();
209  }
210 
211  return lookupObject<objectRegistry>(name, recursive);
212 }
213 
214 
215 Foam::label Foam::objectRegistry::getEvent() const
216 {
217  label curEvent = event_++;
218 
219  if (event_ == labelMax)
220  {
222  {
224  << "Event counter has overflowed. "
225  << "Resetting counter on all dependent objects." << nl
226  << "This might cause extra evaluations." << endl;
227  }
228 
229  // Reset event counter
230  curEvent = 1;
231  event_ = 2;
232 
233  // No need to reset dependent objects; overflow is now handled
234  // in regIOobject::upToDate
235  }
236 
237  return curEvent;
238 }
239 
240 
241 bool Foam::objectRegistry::checkIn(regIOobject* io) const
242 {
243  if (!io) return false;
244 
245  objectRegistry& obr = const_cast<objectRegistry&>(*this);
246 
248  {
249  Pout<< "objectRegistry::checkIn : "
250  << name() << " : checking in " << io->name()
251  << " of type " << io->type()
252  << endl;
253  }
254 
255  // Delete cached object if it has the same name as io, and in the
256  // cacheTemporaryObjects list
257  if (!cacheTemporaryObjects_.empty())
258  {
259  auto cacheIter = cacheTemporaryObjects_.find(io->name());
260 
261  if (cacheIter.good())
262  {
263  iterator iter = obr.find(io->name());
264 
265  if
266  (
267  iter.good()
268  && iter.val() != io
269  && iter.val()->ownedByRegistry()
270  )
271  {
273  {
274  Pout<< "objectRegistry::checkIn : "
275  << name() << " : deleting cached object "
276  << io->name() << endl;
277  }
278 
279  cacheIter.val().first() = false;
280  deleteCachedObject(iter.val());
281  }
282  }
283  }
284 
285 
286  bool ok = obr.insert(io->name(), io);
287 
288  if (!ok && objectRegistry::debug)
289  {
291  << name() << " : Attempt to checkIn object with name "
292  << io->name() << " which was already checked in"
293  << endl;
294  }
295 
296  return ok;
297 }
298 
299 
300 bool Foam::objectRegistry::checkOut(regIOobject* io) const
301 {
302  if (!io) return false;
303 
304  objectRegistry& obr = const_cast<objectRegistry&>(*this);
305 
306  iterator iter = obr.find(io->name());
307 
308  if (iter.good())
309  {
311  {
312  Pout<< "objectRegistry::checkOut : "
313  << name() << " : checking out " << io->name()
314  << " of type " << io->type()
315  << endl;
316  }
317 
318  if (iter.val() != io)
319  {
321  {
323  << name() << " : Attempt to checkOut copy of "
324  << iter.key()
325  << endl;
326  }
327 
328  return false;
329  }
330 
331  return obr.erase(iter);
332  }
333 
334 
336  {
337  Pout<< "objectRegistry::checkOut : "
338  << name() << " : could not find " << io->name() << " in registry"
339  << endl;
340  }
341 
342  return false;
343 }
344 
347 {
348  return checkIn(&io);
349 }
350 
353 {
354  return checkOut(&io);
355 }
356 
358 bool Foam::objectRegistry::checkOut(const word& key) const
359 {
360  return const_cast<objectRegistry&>(*this).erase(key);
361 }
362 
363 
365 {
366  // Free anything owned by the registry, but first unset both
367  // 'ownedByRegistry' and 'registered' flags to ensure that the
368  // regIOobject destructor will not affect the registry
369 
370  for (iterator iter = begin(); iter != end(); ++iter)
371  {
372  regIOobject* ptr = iter.val();
373 
374  if (ptr && ptr->ownedByRegistry())
375  {
377  {
378  Pout<< "objectRegistry::clear : " << ptr->name() << nl;
379  }
380 
381  ptr->release(true); // Relinquish ownership and registration
382  delete ptr; // Delete also clears fileHandler watches
383  }
384  }
385 
387 }
388 
389 
391 {
394 }
395 
396 
397 bool Foam::objectRegistry::erase(const iterator& iter)
398 {
399  // Remove from registry - see notes in objectRegistry::clear()
400 
401  if (iter.good())
402  {
403  regIOobject* ptr = const_cast<iterator&>(iter).val();
404 
405  const bool ok = HashTable<regIOobject*>::erase(iter);
406 
407  if (ptr && ptr->ownedByRegistry())
408  {
409  ptr->release(true); // Relinquish ownership and registration
410  delete ptr; // Delete also clears fileHandler watches
411  }
412 
413  return ok;
414  }
415 
416  return false;
417 }
418 
421 {
422  return erase(find(key));
423 }
424 
426 Foam::label Foam::objectRegistry::erase(std::initializer_list<word> keys)
427 {
428  return eraseImpl(*this, keys.begin(), keys.end());
429 }
430 
432 Foam::label Foam::objectRegistry::erase(const UList<word>& keys)
433 {
434  return eraseImpl(*this, keys.begin(), keys.end());
435 }
436 
437 
438 void Foam::objectRegistry::rename(const word& newName)
439 {
440  regIOobject::rename(newName);
441 
442  // Adjust dbDir_ as well
443  const auto i = dbDir_.rfind('/');
444 
445  if (i == string::npos)
446  {
447  dbDir_ = newName;
448  }
449  else
450  {
451  dbDir_.replace(i+1, string::npos, newName);
452  }
453 }
454 
455 
457 (
458  const word& name,
459  const bool recursive
460 ) const
461 {
462  const_iterator iter = cfind(name);
463 
464  if (iter.good())
465  {
466  return iter.val();
467  }
468  else if (recursive && this->parentNotTime())
469  {
470  return parent_.cfindIOobject(name, recursive);
471  }
472 
473  return nullptr;
474 }
475 
476 
478 (
479  const word& name,
480  const bool recursive
481 ) const
482 {
483  return cfindIOobject(name, recursive);
484 }
485 
486 
488 {
489  for (const_iterator iter = cbegin(); iter != cend(); ++iter)
490  {
491  if (iter.val()->modified())
492  {
493  return true;
494  }
495  }
496 
497  return false;
498 }
499 
500 
502 {
503  for (iterator iter = begin(); iter != end(); ++iter)
504  {
506  {
507  Pout<< "objectRegistry::readModifiedObjects() : "
508  << name() << " : Considering reading object "
509  << iter.key() << endl;
510  }
511 
512  iter.val()->readIfModified();
513  }
514 }
515 
516 
518 {
519  readModifiedObjects();
520  return true;
521 }
522 
523 
525 (
526  IOstreamOption streamOpt,
527  const bool writeOnProc
528 ) const
529 {
530  bool ok = true;
531 
532  for (const_iterator iter = cbegin(); iter != cend(); ++iter)
533  {
535  {
536  const regIOobject& obj = *iter.val();
537 
538  Pout<< "objectRegistry::write() : "
539  << name() << " : Considering writing object "
540  << iter.key() << " of type "
541  << obj.type() << " with writeOpt "
542  << static_cast<int>(obj.writeOpt())
543  << " to file " << obj.objectRelPath() << endl;
544  }
545 
546  if (iter.val()->writeOpt() != IOobjectOption::NO_WRITE)
547  {
548  ok = iter.val()->writeObject(streamOpt, writeOnProc) && ok;
549  }
550  }
551 
552  return ok;
553 }
554 
555 
556 // ************************************************************************* //
bool contains(const word &name, const bool recursive=false) const
Does the registry contain the regIOobject object (by name).
string & replace(const std::string &s1, const std::string &s2, size_type pos=0)
Replace first occurrence of sub-string s1 with s2, beginning at pos.
Definition: string.C:101
label find(const ListType &input, const UnaryPredicate &pred, const label start=0)
Same as ListOps::find_if.
Definition: ListOps.H:795
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
List of names generated by calling name() for each list item and filtered for matches.
void release(const bool unregister=false) noexcept
Set object as not ownedByRegistry.
Definition: regIOobjectI.H:176
void readModifiedObjects()
Read the objects that have been modified.
srcOptions erase("case")
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
bool erase(const iterator &iter)
Erase an entry specified by the given iterator.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
wordList names() const
The unsorted names of all objects.
virtual bool modified() const
Return true if any of the object&#39;s files have been modified.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
bool store()
Register object with its registry and transfer ownership to the registry.
Definition: regIOobjectI.H:36
A simple container for options an IOstream can normally have.
Ignore writing from objectRegistry::writeObject()
const objectRegistry & subRegistry(const word &name, const bool forceCreate=false, const bool recursive=false) const
Lookup and return a const sub-objectRegistry.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
StringType validate(const std::string &str, const UnaryPredicate &accept, const bool invert=false)
Return a copy of the input string with validated characters.
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write the objects using stream options.
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:342
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
Unary and binary predicates that always return true, useful for templating.
Definition: predicates.H:53
writeOption writeOpt() const noexcept
Get the write option.
label count(const char *clsName) const
The number of objects of the given class name.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A class for handling words, derived from Foam::string.
Definition: word.H:63
void clear()
Remove all entries from table.
Definition: HashTable.C:725
wordList sortedNames() const
The sorted names of all objects.
virtual ~objectRegistry()
Destructor, with checkOut() for all objects that are ownedByRegistry.
label getEvent() const
Return new event number.
bool local
Definition: EEqn.H:20
virtual bool readIfModified()
Read object if modified.
constexpr auto cend(const C &c) -> decltype(c.end())
Return const_iterator to the end of the container c.
Definition: stdFoam.H:223
A HashTable similar to std::unordered_map.
Definition: HashTable.H:108
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:391
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
bool isTimeDb() const noexcept
True if the registry is Time.
const direction noexcept
Definition: Scalar.H:258
bool checkOut()
Remove all file watches and remove object from registry.
Definition: regIOobject.C:221
int debug
Static debugging option.
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
defineTypeNameAndDebug(combustionModel, 0)
virtual void rename(const word &newName)
Rename.
Definition: regIOobject.C:484
void clearStorage()
Clear all entries from the registry and the table itself.
constexpr auto cbegin(const C &c) -> decltype(c.begin())
Return const_iterator to the beginning of the container c.
Definition: stdFoam.H:190
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition: HashTable.C:472
#define WarningInFunction
Report a warning using Foam::Warning.
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
bool ownedByRegistry() const noexcept
Is this object owned by the registry?
Definition: regIOobjectI.H:30
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:139
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
Nothing to be read.
Automatically write from objectRegistry::writeObject()
void clear()
Clear all entries from the registry.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:66
fileName objectRelPath() const
The object path relative to the root.
Definition: IOobject.C:524
constexpr label labelMax
Definition: label.H:55
static label eraseImpl(objectRegistry &obr, InputIter first, InputIter last)
List< Key > toc() const
The table of contents (the keys) in unsorted order.
Definition: HashTable.C:124
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:435
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
Registry of regIOobjects.
constexpr auto begin(C &c) -> decltype(c.begin())
Return iterator to the beginning of the container c.
Definition: stdFoam.H:168
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
Request registration (bool: true)
bool checkIn()
Add object to registry, if not already registered.
Definition: regIOobject.C:184
const regIOobject * cfindIOobject(const word &name, const bool recursive=false) const
Return const pointer to the regIOobject.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
virtual void rename(const word &newName)
Rename.
Namespace for OpenFOAM.
void clearStorage()
Remove all entries from table and the table itself.
Definition: HashTable.C:750
HashTable< wordHashSet > classes() const
A summary hash of classes used and their associated object names.