objectRegistry.C 11.6 KB
Newer Older
1
2
3
4
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
OpenFOAM bot's avatar
OpenFOAM bot committed
5
6
7
8
    \\  /    A nd           | Copyright (C) 2015-2019 OpenCFD Ltd.
     \\/     M anipulation  |
-------------------------------------------------------------------------------
                            | Copyright (C) 2011-2017 OpenFOAM Foundation
9
10
11
12
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

13
14
15
16
    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
17
18
19
20
21
22
23

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
24
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
25
26
27
28
29

\*---------------------------------------------------------------------------*/

#include "objectRegistry.H"
#include "Time.H"
30
#include "predicates.H"
31
32
33

// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

34
35
namespace Foam
{
36
    defineTypeNameAndDebug(objectRegistry, 0);
37
}
38
39


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //

namespace Foam
{

// Templated implementation for erase() with iterator range.
// Prefer not to expose directly.
template<class InputIter>
static label eraseImpl(objectRegistry& obr, InputIter first, InputIter last)
{
    label changed = 0;

    for
    (
        const label nTotal = obr.size();
        changed < nTotal && first != last; // Terminate early
        ++first
    )
    {
        if (obr.erase(*first))
        {
            ++changed;
        }
    }

    return changed;
}

} // End namespace Foam


71
72
73
74
75
76
77
78
// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //

bool Foam::objectRegistry::parentNotTime() const
{
    return (&parent_ != dynamic_cast<const objectRegistry*>(&time_));
}


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //

const Foam::regIOobject* Foam::objectRegistry::cfindIOobject
(
    const word& name,
    const bool recursive
) const
{
    const_iterator iter = cfind(name);

    if (iter.found())
    {
        return iter.val();
    }
    else if (recursive && this->parentNotTime())
    {
        return parent_.cfindIOobject(name, recursive);
    }

    return nullptr;
}


102
103
// * * * * * * * * * * * * * * * * Constructors *  * * * * * * * * * * * * * //

104
Foam::objectRegistry::objectRegistry(const Time& t, const label nObjects)
105
106
107
108
109
:
    regIOobject
    (
        IOobject
        (
110
            word::validate(t.caseName()),
111
            t.path(),
112
113
114
115
            t,
            IOobject::NO_READ,
            IOobject::AUTO_WRITE,
            false
mattijs's avatar
mattijs committed
116
117
        ),
        true    // to flag that this is the top-level regIOobject
118
    ),
119
    HashTable<regIOobject*>(nObjects),
120
121
    time_(t),
    parent_(t),
mattijs's avatar
mattijs committed
122
123
    dbDir_(name()),
    event_(1)
124
125
126
{}


127
Foam::objectRegistry::objectRegistry(const IOobject& io, const label nObjects)
128
129
:
    regIOobject(io),
130
    HashTable<regIOobject*>(nObjects),
131
132
    time_(io.time()),
    parent_(io.db()),
mattijs's avatar
mattijs committed
133
134
    dbDir_(parent_.dbDir()/local()/name()),
    event_(1)
135
136
137
138
139
140
141
142
143
{
    writeOpt() = IOobject::AUTO_WRITE;
}


// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //

Foam::objectRegistry::~objectRegistry()
{
144
    objectRegistry::clear();
145
146
147
148
149
}


// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //

150
151
152
153
154
155
Foam::HashTable<Foam::wordHashSet> Foam::objectRegistry::classes() const
{
    return classesImpl(*this, predicates::always());
}


156
157
158
159
160
161
162
Foam::label Foam::objectRegistry::count(const char* clsName) const
{
    // No nullptr check - only called with string literals
    return count(static_cast<word>(clsName));
}


163
164
Foam::wordList Foam::objectRegistry::names() const
{
165
166
    return HashTable<regIOobject*>::toc();
}
167
168


169
170
171
Foam::wordList Foam::objectRegistry::sortedNames() const
{
    return HashTable<regIOobject*>::sortedToc();
172
173
174
}


175
Foam::wordList Foam::objectRegistry::names(const char* clsName) const
176
{
177
178
    // No nullptr check - only called with string literals
    return names(static_cast<word>(clsName));
179
180
181
}


182
Foam::wordList Foam::objectRegistry::sortedNames(const char* clsName) const
183
{
184
185
    // No nullptr check - only called with string literals
    return sortedNames(static_cast<word>(clsName));
186
187
188
}


189
190
const Foam::objectRegistry& Foam::objectRegistry::subRegistry
(
191
    const word& name,
192
193
    const bool forceCreate,
    const bool recursive
194
195
) const
{
196
    if (forceCreate && !foundObject<objectRegistry>(name, recursive))
197
    {
198
        objectRegistry* subObr = new objectRegistry
199
200
201
202
203
204
205
206
207
208
        (
            IOobject
            (
                name,
                time().constant(),
                *this,
                IOobject::NO_READ,
                IOobject::NO_WRITE
            )
        );
209
        subObr->store();
210
    }
211
212

    return lookupObject<objectRegistry>(name, recursive);
213
214
215
}


mattijs's avatar
mattijs committed
216
217
218
219
220
221
Foam::label Foam::objectRegistry::getEvent() const
{
    label curEvent = event_++;

    if (event_ == labelMax)
    {
222
223
        if (objectRegistry::debug)
        {
224
            WarningInFunction
225
226
227
228
                << "Event counter has overflowed. "
                << "Resetting counter on all dependent objects." << nl
                << "This might cause extra evaluations." << endl;
        }
mattijs's avatar
mattijs committed
229
230
231
232
233

        // Reset event counter
        curEvent = 1;
        event_ = 2;

234
235
        // No need to reset dependent objects; overflow is now handled
        // in regIOobject::upToDate
mattijs's avatar
mattijs committed
236
237
238
239
240
241
    }

    return curEvent;
}


242
bool Foam::objectRegistry::checkIn(regIOobject* io) const
243
{
244
245
    if (!io) return false;

246
247
    if (objectRegistry::debug)
    {
248
249
250
        Pout<< "objectRegistry::checkIn : "
            << name() << " : checking in " << io->name()
            << " of type " << io->type()
251
252
253
            << endl;
    }

254
255
    objectRegistry& obr = const_cast<objectRegistry&>(*this);

256
    bool ok = obr.insert(io->name(), io);
257
258
259
260
261

    if (!ok && objectRegistry::debug)
    {
        WarningInFunction
            << name() << " : attempted to checkIn object with name "
262
            << io->name() << " which was already checked in"
263
264
265
266
            << endl;
    }

    return ok;
267
268
269
}


270
bool Foam::objectRegistry::checkOut(regIOobject* io) const
271
{
272
273
    if (!io) return false;

274
275
    objectRegistry& obr = const_cast<objectRegistry&>(*this);

276
    iterator iter = obr.find(io->name());
277

278
    if (iter.found())
279
280
281
    {
        if (objectRegistry::debug)
        {
282
283
284
            Pout<< "objectRegistry::checkOut : "
                << name() << " : checking out " << io->name()
                << " of type " << io->type()
285
286
287
                << endl;
        }

288
        if (iter.val() != io)
289
290
291
        {
            if (objectRegistry::debug)
            {
292
                WarningInFunction
293
294
                    << name() << " : attempt to checkOut copy of "
                    << iter.key()
295
296
297
298
299
                    << endl;
            }

            return false;
        }
mattijs's avatar
mattijs committed
300

301
302
        return obr.erase(iter);
    }
mattijs's avatar
mattijs committed
303

304

305
    if (objectRegistry::debug)
306
    {
307
308
        Pout<< "objectRegistry::checkOut : "
            << name() << " : could not find " << io->name() << " in registry"
309
            << endl;
Mark Olesen's avatar
Mark Olesen committed
310
    }
311

Mark Olesen's avatar
Mark Olesen committed
312
313
314
315
    return false;
}


316
317
318
319
320
321
322
323
324
325
326
327
bool Foam::objectRegistry::checkIn(regIOobject& io) const
{
    return checkIn(&io);
}


bool Foam::objectRegistry::checkOut(regIOobject& io) const
{
    return checkOut(&io);
}


328
329
330
331
332
333
bool Foam::objectRegistry::checkOut(const word& key) const
{
    return const_cast<objectRegistry&>(*this).erase(key);
}


334
335
336
void Foam::objectRegistry::clear()
{
    // Free anything owned by the registry
337
338
339
340
341
342
343
344
    // This needs to be done in two stages:
    // - collect objects-to-be-removed
    // - actually delete objects
    // since the destructor of the regIOobject will actually delete its
    // entry from the objectRegistry which messes up the iterator.

    DynamicList<regIOobject*> owned;

345
346
347
348
349
350
    for (iterator iter = begin(); iter != end(); ++iter)
    {
        regIOobject* ptr = iter.val();

        if (ptr && ptr->ownedByRegistry())
        {
351
352
353
354
355
356
357
            // TBD: may wish to have ptr->clearWatches();
            if (objectRegistry::debug)
            {
                Pout<< "objectRegistry::clear : " << ptr->name()
                    <<  " watches :" << flatOutput(ptr->watchIndices()) << nl;

            }
358
359

            owned.append(ptr);
360
361
362
        }
    }

363
364
365
366
367
368
369
370
    for (regIOobject* objectPtr : owned)
    {
        // Make sure that the destructor of the regIOobject does a checkout
        objectPtr->release();

        delete objectPtr;
    }

371
372
373
374
375
376
377
378
379
380
381
    HashTable<regIOobject*>::clear();
}


void Foam::objectRegistry::clearStorage()
{
    objectRegistry::clear();
    HashTable<regIOobject*>::clearStorage();
}


382
383
384
385
386
387
388
389
390
391
392
393
bool Foam::objectRegistry::erase(const iterator& iter)
{
    // Free anything owned by the registry

    if (iter.found())
    {
        regIOobject* ptr = iter.val();

        bool ok = HashTable<regIOobject*>::erase(iter);

        if (ptr && ptr->ownedByRegistry())
        {
394
            // TBD: may wish to have ptr->clearWatches();
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
            delete ptr;
        }

        return ok;
    }

    return false;
}


bool Foam::objectRegistry::erase(const word& key)
{
    return erase(find(key));
}


Foam::label Foam::objectRegistry::erase(std::initializer_list<word> keys)
{
     return eraseImpl(*this, keys.begin(), keys.end());
}


Foam::label Foam::objectRegistry::erase(const UList<word>& keys)
{
    return eraseImpl(*this, keys.begin(), keys.end());
}


Mark Olesen's avatar
Mark Olesen committed
423
424
425
void Foam::objectRegistry::rename(const word& newName)
{
    regIOobject::rename(newName);
426

427
428
    // Adjust dbDir_ as well
    const auto i = dbDir_.rfind('/');
Mark Olesen's avatar
Mark Olesen committed
429
430
431
432
433
434
435
436

    if (i == string::npos)
    {
        dbDir_ = newName;
    }
    else
    {
        dbDir_.replace(i+1, string::npos, newName);
437
438
439
440
    }
}


441
442
443
444
445
446
447
448
449
450
bool Foam::objectRegistry::found
(
    const word& name,
    const bool recursive
) const
{
    return cfindIOobject(name, recursive);
}


451
452
bool Foam::objectRegistry::modified() const
{
453
    for (const_iterator iter = cbegin(); iter != cend(); ++iter)
454
    {
455
        if (iter->modified())
456
        {
457
            return true;
458
459
460
        }
    }

461
    return false;
462
463
464
465
466
467
468
469
470
471
472
}


void Foam::objectRegistry::readModifiedObjects()
{
    for (iterator iter = begin(); iter != end(); ++iter)
    {
        if (objectRegistry::debug)
        {
            Pout<< "objectRegistry::readModifiedObjects() : "
                << name() << " : Considering reading object "
473
                << iter.key() << endl;
474
475
        }

476
        iter->readIfModified();
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
    }
}


bool Foam::objectRegistry::readIfModified()
{
    readModifiedObjects();
    return true;
}


bool Foam::objectRegistry::writeObject
(
    IOstream::streamFormat fmt,
    IOstream::versionNumber ver,
492
493
    IOstream::compressionType cmp,
    const bool valid
494
495
496
497
) const
{
    bool ok = true;

498
    for (const_iterator iter = cbegin(); iter != cend(); ++iter)
499
500
501
502
503
    {
        if (objectRegistry::debug)
        {
            Pout<< "objectRegistry::write() : "
                << name() << " : Considering writing object "
504
                << iter.key()
505
                << " of type " << iter->type()
506
                << " with writeOpt " << static_cast<int>(iter->writeOpt())
507
                << " to file " << iter->objectPath()
508
509
510
                << endl;
        }

511
        if (iter->writeOpt() != NO_WRITE)
512
        {
513
            ok = iter->writeObject(fmt, ver, cmp, valid) && ok;
514
515
516
517
518
519
520
521
        }
    }

    return ok;
}


// ************************************************************************* //