update readme
[c11concurrency-benchmarks.git] / silo / str_arena.h
1 #pragma once
2
3 #include <string>
4 #include <memory>
5 #include "small_vector.h"
6
7 // XXX: str arena hardcoded now to handle at most 1024 strings
8 class str_arena {
9 public:
10
11   static const size_t PreAllocBufSize = 256;
12   static const size_t NStrs = 1024;
13
14   static const size_t MinStrReserveLength = 2 * CACHELINE_SIZE;
15   static_assert(PreAllocBufSize >= MinStrReserveLength, "xx");
16
17   str_arena()
18     : n(0)
19   {
20     for (size_t i = 0; i < NStrs; i++)
21       strs[i].reserve(PreAllocBufSize);
22   }
23
24   // non-copyable/non-movable for the time being
25   str_arena(str_arena &&) = delete;
26   str_arena(const str_arena &) = delete;
27   str_arena &operator=(const str_arena &) = delete;
28
29   inline void
30   reset()
31   {
32     n = 0;
33     overflow.clear();
34   }
35
36   // next() is guaranteed to return an empty string
37   std::string *
38   next()
39   {
40     if (likely(n < NStrs)) {
41       std::string * const px = &strs[n++];
42       px->clear();
43       INVARIANT(manages(px));
44       return px;
45     }
46     // only loaders need this- and this allows us to use a unified
47     // str_arena for loaders/workers
48     overflow.emplace_back(new std::string);
49     ++n;
50     return overflow.back().get();
51   }
52
53   inline std::string *
54   operator()()
55   {
56     return next();
57   }
58
59   void
60   return_last(std::string *px)
61   {
62     INVARIANT(n > 0);
63     --n;
64   }
65
66   bool
67   manages(const std::string *px) const
68   {
69     return manages_local(px) || manages_overflow(px);
70   }
71
72 private:
73
74   bool
75   manages_local(const std::string *px) const
76   {
77     if (px < &strs[0])
78       return false;
79     if (px >= &strs[NStrs])
80       return false;
81     return 0 == ((reinterpret_cast<const char *>(px) -
82                   reinterpret_cast<const char *>(&strs[0])) % sizeof(std::string));
83   }
84
85   bool
86   manages_overflow(const std::string *px) const
87   {
88     for (auto &p : overflow)
89       if (p.get() == px)
90         return true;
91     return false;
92   }
93
94 private:
95   std::string strs[NStrs];
96   std::vector<std::unique_ptr<std::string>> overflow;
97   size_t n;
98 };
99
100 class scoped_str_arena {
101 public:
102   scoped_str_arena(str_arena *arena)
103     : arena(arena)
104   {
105   }
106
107   scoped_str_arena(str_arena &arena)
108     : arena(&arena)
109   {
110   }
111
112   scoped_str_arena(scoped_str_arena &&) = default;
113
114   // non-copyable
115   scoped_str_arena(const scoped_str_arena &) = delete;
116   scoped_str_arena &operator=(const scoped_str_arena &) = delete;
117
118
119   ~scoped_str_arena()
120   {
121     if (arena)
122       arena->reset();
123   }
124
125   inline ALWAYS_INLINE str_arena *
126   get()
127   {
128     return arena;
129   }
130
131 private:
132   str_arena *arena;
133 };