Home | History | Annotate | Download | only in ADT
      1 //===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
     11 // These can be used to write iterators that are fail-fast when LLVM is built
     12 // with asserts enabled.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef LLVM_ADT_EPOCH_TRACKER_H
     17 #define LLVM_ADT_EPOCH_TRACKER_H
     18 
     19 #include "llvm/Config/abi-breaking.h"
     20 #include "llvm/Config/llvm-config.h"
     21 
     22 #include <cstdint>
     23 
     24 namespace llvm {
     25 
     26 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
     27 
     28 /// \brief A base class for data structure classes wishing to make iterators
     29 /// ("handles") pointing into themselves fail-fast.  When building without
     30 /// asserts, this class is empty and does nothing.
     31 ///
     32 /// DebugEpochBase does not by itself track handles pointing into itself.  The
     33 /// expectation is that routines touching the handles will poll on
     34 /// isHandleInSync at appropriate points to assert that the handle they're using
     35 /// is still valid.
     36 ///
     37 class DebugEpochBase {
     38   uint64_t Epoch;
     39 
     40 public:
     41   DebugEpochBase() : Epoch(0) {}
     42 
     43   /// \brief Calling incrementEpoch invalidates all handles pointing into the
     44   /// calling instance.
     45   void incrementEpoch() { ++Epoch; }
     46 
     47   /// \brief The destructor calls incrementEpoch to make use-after-free bugs
     48   /// more likely to crash deterministically.
     49   ~DebugEpochBase() { incrementEpoch(); }
     50 
     51   /// \brief A base class for iterator classes ("handles") that wish to poll for
     52   /// iterator invalidating modifications in the underlying data structure.
     53   /// When LLVM is built without asserts, this class is empty and does nothing.
     54   ///
     55   /// HandleBase does not track the parent data structure by itself.  It expects
     56   /// the routines modifying the data structure to call incrementEpoch when they
     57   /// make an iterator-invalidating modification.
     58   ///
     59   class HandleBase {
     60     const uint64_t *EpochAddress;
     61     uint64_t EpochAtCreation;
     62 
     63   public:
     64     HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
     65 
     66     explicit HandleBase(const DebugEpochBase *Parent)
     67         : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
     68 
     69     /// \brief Returns true if the DebugEpochBase this Handle is linked to has
     70     /// not called incrementEpoch on itself since the creation of this
     71     /// HandleBase instance.
     72     bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
     73 
     74     /// \brief Returns a pointer to the epoch word stored in the data structure
     75     /// this handle points into.  Can be used to check if two iterators point
     76     /// into the same data structure.
     77     const void *getEpochAddress() const { return EpochAddress; }
     78   };
     79 };
     80 
     81 #else
     82 
     83 class DebugEpochBase {
     84 public:
     85   void incrementEpoch() {}
     86 
     87   class HandleBase {
     88   public:
     89     HandleBase() = default;
     90     explicit HandleBase(const DebugEpochBase *) {}
     91     bool isHandleInSync() const { return true; }
     92     const void *getEpochAddress() const { return nullptr; }
     93   };
     94 };
     95 
     96 #endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
     97 
     98 } // namespace llvm
     99 
    100 #endif
    101