benchmark silo added
[c11concurrency-benchmarks.git] / silo / str_arena.h
diff --git a/silo/str_arena.h b/silo/str_arena.h
new file mode 100644 (file)
index 0000000..c596918
--- /dev/null
@@ -0,0 +1,133 @@
+#pragma once
+
+#include <string>
+#include <memory>
+#include "small_vector.h"
+
+// XXX: str arena hardcoded now to handle at most 1024 strings
+class str_arena {
+public:
+
+  static const size_t PreAllocBufSize = 256;
+  static const size_t NStrs = 1024;
+
+  static const size_t MinStrReserveLength = 2 * CACHELINE_SIZE;
+  static_assert(PreAllocBufSize >= MinStrReserveLength, "xx");
+
+  str_arena()
+    : n(0)
+  {
+    for (size_t i = 0; i < NStrs; i++)
+      strs[i].reserve(PreAllocBufSize);
+  }
+
+  // non-copyable/non-movable for the time being
+  str_arena(str_arena &&) = delete;
+  str_arena(const str_arena &) = delete;
+  str_arena &operator=(const str_arena &) = delete;
+
+  inline void
+  reset()
+  {
+    n = 0;
+    overflow.clear();
+  }
+
+  // next() is guaranteed to return an empty string
+  std::string *
+  next()
+  {
+    if (likely(n < NStrs)) {
+      std::string * const px = &strs[n++];
+      px->clear();
+      INVARIANT(manages(px));
+      return px;
+    }
+    // only loaders need this- and this allows us to use a unified
+    // str_arena for loaders/workers
+    overflow.emplace_back(new std::string);
+    ++n;
+    return overflow.back().get();
+  }
+
+  inline std::string *
+  operator()()
+  {
+    return next();
+  }
+
+  void
+  return_last(std::string *px)
+  {
+    INVARIANT(n > 0);
+    --n;
+  }
+
+  bool
+  manages(const std::string *px) const
+  {
+    return manages_local(px) || manages_overflow(px);
+  }
+
+private:
+
+  bool
+  manages_local(const std::string *px) const
+  {
+    if (px < &strs[0])
+      return false;
+    if (px >= &strs[NStrs])
+      return false;
+    return 0 == ((reinterpret_cast<const char *>(px) -
+                  reinterpret_cast<const char *>(&strs[0])) % sizeof(std::string));
+  }
+
+  bool
+  manages_overflow(const std::string *px) const
+  {
+    for (auto &p : overflow)
+      if (p.get() == px)
+        return true;
+    return false;
+  }
+
+private:
+  std::string strs[NStrs];
+  std::vector<std::unique_ptr<std::string>> overflow;
+  size_t n;
+};
+
+class scoped_str_arena {
+public:
+  scoped_str_arena(str_arena *arena)
+    : arena(arena)
+  {
+  }
+
+  scoped_str_arena(str_arena &arena)
+    : arena(&arena)
+  {
+  }
+
+  scoped_str_arena(scoped_str_arena &&) = default;
+
+  // non-copyable
+  scoped_str_arena(const scoped_str_arena &) = delete;
+  scoped_str_arena &operator=(const scoped_str_arena &) = delete;
+
+
+  ~scoped_str_arena()
+  {
+    if (arena)
+      arena->reset();
+  }
+
+  inline ALWAYS_INLINE str_arena *
+  get()
+  {
+    return arena;
+  }
+
+private:
+  str_arena *arena;
+};