зеркало из https://github.com/mozilla/gecko-dev.git
64 строки
1.6 KiB
C++
64 строки
1.6 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef RecurseGuard_h__
|
|
#define RecurseGuard_h__
|
|
|
|
#include "Utils.h"
|
|
|
|
// This class acts as a tracker for avoiding infinite recursion when traversing
|
|
// chains in CFGs etc.
|
|
//
|
|
// Constructing a RecurseGuard sets up a shared backing store which tracks the
|
|
// currently observed objects. Whenever recursing, use RecurseGuard.recurse(T)
|
|
// to construct another RecurseGuard with the same backing store.
|
|
//
|
|
// The RecurseGuard object will unregister its object when it is destroyed, and
|
|
// has a method `isRepeat()` which will return `true` if the item was already
|
|
// seen.
|
|
template<typename T>
|
|
class RecurseGuard {
|
|
public:
|
|
RecurseGuard(T Thing) : Thing(Thing), Set(new DenseSet<T>()), Repeat(false) {
|
|
Set->insert(Thing);
|
|
}
|
|
RecurseGuard(T Thing, std::shared_ptr<DenseSet<T>>& Set)
|
|
: Thing(Thing), Set(Set), Repeat(false) {
|
|
Repeat = !Set->insert(Thing).second;
|
|
}
|
|
RecurseGuard(const RecurseGuard &) = delete;
|
|
RecurseGuard(RecurseGuard && Other)
|
|
: Thing(Other.Thing), Set(Other.Set), Repeat(Other.Repeat) {
|
|
Other.Repeat = true;
|
|
}
|
|
~RecurseGuard() {
|
|
if (!Repeat) {
|
|
Set->erase(Thing);
|
|
}
|
|
}
|
|
|
|
bool isRepeat() { return Repeat; }
|
|
|
|
T get() { return Thing; }
|
|
|
|
operator T() {
|
|
return Thing;
|
|
}
|
|
|
|
T operator ->() {
|
|
return Thing;
|
|
}
|
|
|
|
RecurseGuard recurse(T NewThing) {
|
|
return RecurseGuard(NewThing, Set);
|
|
}
|
|
|
|
private:
|
|
T Thing;
|
|
std::shared_ptr<DenseSet<T>> Set;
|
|
bool Repeat;
|
|
};
|
|
|
|
#endif // RecurseGuard_h__
|