about summary refs log tree commit diff homepage
path: root/include
diff options
context:
space:
mode:
authorMartin Nowack <m.nowack@imperial.ac.uk>2019-04-03 16:01:36 +0100
committerCristian Cadar <c.cadar@imperial.ac.uk>2020-02-19 12:05:22 +0000
commit288e3110e5df232ab471db705371d818605b4ae4 (patch)
tree0d36b9dc49581b9b335cc962f0896c13e2756993 /include
parentb723470d00f80ad5620b27e81f2afa9efdd95135 (diff)
downloadklee-288e3110e5df232ab471db705371d818605b4ae4.tar.gz
Add `ReferenceCounter` struct utilized by ref<>
Using KLEE's `ref<>` shared ptr requires the referenced object
to contain a reference counter to be added and initialised to 0
as part of the constructor.

To support better reuse of the `ref<>` ptr add a `ReferenceCounter`
struct.

Just adding this struct to a new class/struct as member enables
reference counting with `ref<>` - no additional counter management
needed.
Diffstat (limited to 'include')
-rw-r--r--include/klee/Expr/Expr.h5
-rw-r--r--include/klee/MergeHandler.h10
-rw-r--r--include/klee/util/Ref.h72
3 files changed, 73 insertions, 14 deletions
diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h
index d4e4f7fa..b979596a 100644
--- a/include/klee/Expr/Expr.h
+++ b/include/klee/Expr/Expr.h
@@ -174,7 +174,8 @@ public:
     CmpKindLast=Sge
   };
 
-  unsigned refCount;
+  /// @brief Required by klee::ref-managed objects
+  class ReferenceCounter _refCount;
 
 protected:  
   unsigned hashValue;
@@ -204,7 +205,7 @@ protected:
   virtual int compareContents(const Expr &b) const = 0;
 
 public:
-  Expr() : refCount(0) { Expr::count++; }
+  Expr() { Expr::count++; }
   virtual ~Expr() { Expr::count--; } 
 
   virtual Kind getKind() const = 0;
diff --git a/include/klee/MergeHandler.h b/include/klee/MergeHandler.h
index d189e46f..48b67467 100644
--- a/include/klee/MergeHandler.h
+++ b/include/klee/MergeHandler.h
@@ -69,10 +69,11 @@
 #ifndef KLEE_MERGEHANDLER_H
 #define KLEE_MERGEHANDLER_H
 
-#include <vector>
+#include "klee/util/Ref.h"
+#include "llvm/Support/CommandLine.h"
 #include <map>
 #include <stdint.h>
-#include "llvm/Support/CommandLine.h"
+#include <vector>
 
 namespace llvm {
 class Instruction;
@@ -143,9 +144,8 @@ public:
   // klee_close_merge
   double getMean();
 
-  /// @brief Required by klee::ref objects
-  unsigned refCount;
-
+  /// @brief Required by klee::ref-managed objects
+  class ReferenceCounter _refCount;
 
   MergeHandler(Executor *_executor, ExecutionState *es);
   ~MergeHandler();
diff --git a/include/klee/util/Ref.h b/include/klee/util/Ref.h
index 44f3f49e..f6d66d16 100644
--- a/include/klee/util/Ref.h
+++ b/include/klee/util/Ref.h
@@ -7,6 +7,25 @@
 //
 //===----------------------------------------------------------------------===//
 
+/**
+ * @file Ref.h
+ * @brief Implements smart-pointer ref<> used by KLEE.
+ *
+ * ## Basic usage:
+ *
+ * Add the following to your struct/class to enable ref<> pointer usage
+ * @code{.cpp}
+ *
+ * struct MyStruct{
+ *   ...
+ *   /// @brief Required by klee::ref-managed objects
+ *   class ReferenceCounter _refCount;
+ *   ...
+ * }
+ * @endcode
+ *
+ */
+
 #ifndef KLEE_REF_H
 #define KLEE_REF_H
 
@@ -22,27 +41,66 @@ using llvm::dyn_cast_or_null;
 
 namespace llvm {
   class raw_ostream;
-}
+} // namespace llvm
 
 namespace klee {
 
 template<class T>
+class ref;
+
+/// Reference counter to be used as part of a ref-managed struct or class
+class ReferenceCounter {
+  template<class T>
+  friend class ref;
+
+  /// Count how often the object has been referenced.
+  unsigned refCount = 0;
+
+public:
+  ReferenceCounter() = default;
+  ~ReferenceCounter() = default;
+
+  // Explicitly initialise reference counter with 0 again
+  // As this object is part of another object, the copy-constructor
+  // might be invoked as part of the other one.
+  ReferenceCounter(const ReferenceCounter& ) {}
+
+  /// Returns the number of parallel references of this objects
+  /// \return number of references on this object
+  unsigned getCount() {return refCount;}
+
+  // Copy assignment operator
+  ReferenceCounter &operator=(const ReferenceCounter &a) {
+    if (this == &a)
+      return *this;
+    // The new copy won't be referenced
+    refCount = 0;
+    return *this;
+  }
+
+  // Do not allow move operations for the reference counter
+  // as otherwise, references become incorrect.
+  ReferenceCounter(ReferenceCounter &&r) noexcept = delete;
+  ReferenceCounter &operator=(ReferenceCounter &&other) noexcept = delete;
+};
+
+template<class T>
 class ref {
   T *ptr;
 
 public:
   // default constructor: create a NULL reference
-  ref() : ptr(0) { }
+  ref() : ptr(nullptr) {}
   ~ref () { dec (); }
 
 private:
   void inc() const {
     if (ptr)
-      ++ptr->refCount;
+      ++ptr->_refCount.refCount;
   }
 
   void dec() const {
-    if (ptr && --ptr->refCount == 0)
+    if (ptr && --ptr->_refCount.refCount == 0)
       delete ptr;
   }
 
@@ -121,7 +179,7 @@ public:
     return ptr;
   }
 
-  bool isNull() const { return ptr == 0; }
+  bool isNull() const { return ptr == nullptr; }
 
   // assumes non-null arguments
   int compare(const ref &rhs) const {
@@ -158,7 +216,7 @@ namespace llvm {
   // isNull semantics, which doesn't seem like a good idea.
 template<typename T>
 struct simplify_type<const ::klee::ref<T> > {
-  typedef T* SimpleType;
+  using SimpleType = T *;
   static SimpleType getSimplifiedValue(const ::klee::ref<T> &Ref) {
     return Ref.get();
   }
@@ -167,6 +225,6 @@ struct simplify_type<const ::klee::ref<T> > {
 template<typename T>
 struct simplify_type< ::klee::ref<T> >
   : public simplify_type<const ::klee::ref<T> > {};
-}
+}  // namespace llvm
 
 #endif /* KLEE_REF_H */