-
Notifications
You must be signed in to change notification settings - Fork 117
/
imstring.h
125 lines (101 loc) · 2.53 KB
/
imstring.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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_ */