mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	MozReview-Commit-ID: AXrQEjWzxvg --HG-- extra : rebase_source : bf972fbb22648af2edbb756eb899ebddf8444dbc
		
			
				
	
	
		
			56 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			56 lines
		
	
	
	
		
			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__
 |