benchmark silo added
[c11concurrency-benchmarks.git] / silo / imstring.h
diff --git a/silo/imstring.h b/silo/imstring.h
new file mode 100644 (file)
index 0000000..f46834b
--- /dev/null
@@ -0,0 +1,125 @@
+#ifndef _NDB_IMSTRING_H_
+#define _NDB_IMSTRING_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#include <algorithm>
+#include <string>
+#include <limits>
+
+#include "macros.h"
+#include "rcu.h"
+#include "util.h"
+#include "counter.h"
+
+/**
+ * Not-really-immutable string, for perf reasons. Also can use
+ * RCU for GC
+ */
+template <bool RCU>
+class base_imstring {
+
+  template <bool R>
+  friend class base_imstring;
+
+  // we can't really support keys > 65536, but most DBs impose
+  // limits on keys
+  typedef uint16_t internal_size_type;
+
+  static inline ALWAYS_INLINE internal_size_type
+  CheckBounds(size_t l)
+  {
+    INVARIANT(l <= std::numeric_limits<internal_size_type>::max());
+    return l;
+  }
+
+  static event_counter g_evt_imstring_bytes_allocated;
+  static event_counter g_evt_imstring_bytes_freed;
+  static event_avg_counter g_evt_avg_imstring_len;
+
+public:
+  base_imstring() : p(NULL), l(0) {}
+
+  base_imstring(const uint8_t *src, size_t l)
+    : p(new uint8_t[l]), l(CheckBounds(l))
+  {
+    g_evt_imstring_bytes_allocated += l;
+    g_evt_avg_imstring_len.offer(l);
+    NDB_MEMCPY(p, src, l);
+  }
+
+  base_imstring(const std::string &s)
+    : p(new uint8_t[s.size()]), l(CheckBounds(s.size()))
+  {
+    g_evt_imstring_bytes_allocated += l;
+    g_evt_avg_imstring_len.offer(l);
+    NDB_MEMCPY(p, s.data(), l);
+  }
+
+  base_imstring(const base_imstring &) = delete;
+  base_imstring(base_imstring &&) = delete;
+  base_imstring &operator=(const base_imstring &) = delete;
+
+  template <bool R>
+  inline void
+  swap(base_imstring<R> &that)
+  {
+    // std::swap() doesn't work for packed elems
+    uint8_t * const temp_p = p;
+    p = that.p;
+    that.p = temp_p;
+    internal_size_type const temp_l = l;
+    l = that.l;
+    that.l = temp_l;
+  }
+
+  inline
+  ~base_imstring()
+  {
+    release();
+    g_evt_imstring_bytes_freed += l;
+  }
+
+  inline const uint8_t *
+  data() const
+  {
+    return p;
+  }
+
+  inline size_t
+  size() const
+  {
+    return l;
+  }
+
+private:
+
+  inline void
+  release()
+  {
+    if (likely(p)) {
+      if (RCU)
+        rcu::s_instance.free_array(p);
+      else
+        delete [] p;
+    }
+  }
+
+  uint8_t *p;
+  internal_size_type l;
+} PACKED;
+
+template <bool RCU>
+event_counter base_imstring<RCU>::g_evt_imstring_bytes_allocated("imstring_bytes_allocated");
+
+template <bool RCU>
+event_counter base_imstring<RCU>::g_evt_imstring_bytes_freed("imstring_bytes_freed");
+
+template <bool RCU>
+event_avg_counter base_imstring<RCU>::g_evt_avg_imstring_len("avg_imstring_len");
+
+typedef base_imstring<false> imstring;
+typedef base_imstring<true>  rcu_imstring;
+
+#endif /* _NDB_IMSTRING_H_ */