Source code

Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#ifndef RecurseGuard_h__
6
#define RecurseGuard_h__
7
8
#include "Utils.h"
9
10
// This class acts as a tracker for avoiding infinite recursion when traversing
11
// chains in CFGs etc.
12
//
13
// Constructing a RecurseGuard sets up a shared backing store which tracks the
14
// currently observed objects. Whenever recursing, use RecurseGuard.recurse(T)
15
// to construct another RecurseGuard with the same backing store.
16
//
17
// The RecurseGuard object will unregister its object when it is destroyed, and
18
// has a method `isRepeat()` which will return `true` if the item was already
19
// seen.
20
template <typename T> class RecurseGuard {
21
public:
22
RecurseGuard(T Thing) : Thing(Thing), Set(new DenseSet<T>()), Repeat(false) {
23
Set->insert(Thing);
24
}
25
RecurseGuard(T Thing, std::shared_ptr<DenseSet<T>> &Set)
26
: Thing(Thing), Set(Set), Repeat(false) {
27
Repeat = !Set->insert(Thing).second;
28
}
29
RecurseGuard(const RecurseGuard &) = delete;
30
RecurseGuard(RecurseGuard &&Other)
31
: Thing(Other.Thing), Set(Other.Set), Repeat(Other.Repeat) {
32
Other.Repeat = true;
33
}
34
~RecurseGuard() {
35
if (!Repeat) {
36
Set->erase(Thing);
37
}
38
}
39
40
bool isRepeat() { return Repeat; }
41
42
T get() { return Thing; }
43
44
operator T() { return Thing; }
45
46
T operator->() { return Thing; }
47
48
RecurseGuard recurse(T NewThing) { return RecurseGuard(NewThing, Set); }
49
50
private:
51
T Thing;
52
std::shared_ptr<DenseSet<T>> Set;
53
bool Repeat;
54
};
55
56
#endif // RecurseGuard_h__