edits
[c11concurrency-benchmarks.git] / silo / imstring.h
1 #ifndef _NDB_IMSTRING_H_
2 #define _NDB_IMSTRING_H_
3
4 #include <stdint.h>
5 #include <string.h>
6
7 #include <algorithm>
8 #include <string>
9 #include <limits>
10
11 #include "macros.h"
12 #include "rcu.h"
13 #include "util.h"
14 #include "counter.h"
15
16 /**
17  * Not-really-immutable string, for perf reasons. Also can use
18  * RCU for GC
19  */
20 template <bool RCU>
21 class base_imstring {
22
23   template <bool R>
24   friend class base_imstring;
25
26   // we can't really support keys > 65536, but most DBs impose
27   // limits on keys
28   typedef uint16_t internal_size_type;
29
30   static inline ALWAYS_INLINE internal_size_type
31   CheckBounds(size_t l)
32   {
33     INVARIANT(l <= std::numeric_limits<internal_size_type>::max());
34     return l;
35   }
36
37   static event_counter g_evt_imstring_bytes_allocated;
38   static event_counter g_evt_imstring_bytes_freed;
39   static event_avg_counter g_evt_avg_imstring_len;
40
41 public:
42   base_imstring() : p(NULL), l(0) {}
43
44   base_imstring(const uint8_t *src, size_t l)
45     : p(new uint8_t[l]), l(CheckBounds(l))
46   {
47     g_evt_imstring_bytes_allocated += l;
48     g_evt_avg_imstring_len.offer(l);
49     NDB_MEMCPY(p, src, l);
50   }
51
52   base_imstring(const std::string &s)
53     : p(new uint8_t[s.size()]), l(CheckBounds(s.size()))
54   {
55     g_evt_imstring_bytes_allocated += l;
56     g_evt_avg_imstring_len.offer(l);
57     NDB_MEMCPY(p, s.data(), l);
58   }
59
60   base_imstring(const base_imstring &) = delete;
61   base_imstring(base_imstring &&) = delete;
62   base_imstring &operator=(const base_imstring &) = delete;
63
64   template <bool R>
65   inline void
66   swap(base_imstring<R> &that)
67   {
68     // std::swap() doesn't work for packed elems
69     uint8_t * const temp_p = p;
70     p = that.p;
71     that.p = temp_p;
72     internal_size_type const temp_l = l;
73     l = that.l;
74     that.l = temp_l;
75   }
76
77   inline
78   ~base_imstring()
79   {
80     release();
81     g_evt_imstring_bytes_freed += l;
82   }
83
84   inline const uint8_t *
85   data() const
86   {
87     return p;
88   }
89
90   inline size_t
91   size() const
92   {
93     return l;
94   }
95
96 private:
97
98   inline void
99   release()
100   {
101     if (likely(p)) {
102       if (RCU)
103         rcu::s_instance.free_array(p);
104       else
105         delete [] p;
106     }
107   }
108
109   uint8_t *p;
110   internal_size_type l;
111 } PACKED;
112
113 template <bool RCU>
114 event_counter base_imstring<RCU>::g_evt_imstring_bytes_allocated("imstring_bytes_allocated");
115
116 template <bool RCU>
117 event_counter base_imstring<RCU>::g_evt_imstring_bytes_freed("imstring_bytes_freed");
118
119 template <bool RCU>
120 event_avg_counter base_imstring<RCU>::g_evt_avg_imstring_len("avg_imstring_len");
121
122 typedef base_imstring<false> imstring;
123 typedef base_imstring<true>  rcu_imstring;
124
125 #endif /* _NDB_IMSTRING_H_ */