Pass type as param to VectorRef instead of bool

This commit is contained in:
mpilman 2019-07-15 14:46:00 -07:00
parent 707b29cbcc
commit 54416f46fd
3 changed files with 105 additions and 81 deletions

View File

@ -159,7 +159,7 @@ struct WatchValueRequest {
struct GetKeyValuesReply : public LoadBalancedReply {
constexpr static FileIdentifier file_identifier = 1783066;
Arena arena;
VectorRef<KeyValueRef, true> data;
VectorRef<KeyValueRef, VecSerStrategy::String> data;
Version version; // useful when latestVersion was requested
bool more;

View File

@ -1028,7 +1028,7 @@ ACTOR Future<Void> getShardStateQ( StorageServer* data, GetShardStateRequest req
return Void();
}
void merge( Arena& arena, VectorRef<KeyValueRef, true>& output, VectorRef<KeyValueRef> const& base,
void merge( Arena& arena, VectorRef<KeyValueRef, VecSerStrategy::String>& output, VectorRef<KeyValueRef> const& base,
StorageServer::VersionedData::iterator& start, StorageServer::VersionedData::iterator const& end,
int versionedDataCount, int limit, bool stopAtEndOfBase, int limitBytes = 1<<30 )
// Combines data from base (at an older version) with sets from newer versions in [start, end) and appends the first (up to) |limit| rows to output

View File

@ -825,13 +825,17 @@ struct string_serialized_traits : std::false_type {
}
};
template <class T, bool>
enum class VecSerStrategy {
FlatBuffers, String
};
template <class T, VecSerStrategy>
struct VectorRefPreserializer {
VectorRefPreserializer() {}
VectorRefPreserializer(const VectorRefPreserializer<T, true>&) {}
VectorRefPreserializer& operator=(const VectorRefPreserializer<T, true>&) { return *this; }
VectorRefPreserializer(const VectorRefPreserializer<T, false>&) {}
VectorRefPreserializer& operator=(const VectorRefPreserializer<T, false>&) { return *this; }
VectorRefPreserializer(const VectorRefPreserializer<T, VecSerStrategy::FlatBuffers>&) {}
VectorRefPreserializer& operator=(const VectorRefPreserializer<T, VecSerStrategy::FlatBuffers>&) { return *this; }
VectorRefPreserializer(const VectorRefPreserializer<T, VecSerStrategy::String>&) {}
VectorRefPreserializer& operator=(const VectorRefPreserializer<T, VecSerStrategy::String>&) { return *this; }
void invalidate() {}
void add(const T& item) {}
@ -839,18 +843,22 @@ struct VectorRefPreserializer {
};
template <class T>
struct VectorRefPreserializer<T, true> {
struct VectorRefPreserializer<T, VecSerStrategy::String> {
mutable int32_t _cached_size; // -1 means unknown
string_serialized_traits<T> _string_traits;
VectorRefPreserializer() : _cached_size(0) {}
VectorRefPreserializer(const VectorRefPreserializer<T, true>& other) : _cached_size(other._cached_size) {}
VectorRefPreserializer& operator=(const VectorRefPreserializer<T, true>& other) {
VectorRefPreserializer(const VectorRefPreserializer<T, VecSerStrategy::String>& other)
: _cached_size(other._cached_size) {}
VectorRefPreserializer& operator=(const VectorRefPreserializer<T, VecSerStrategy::String>& other) {
_cached_size = other._cached_size;
return *this;
}
VectorRefPreserializer(const VectorRefPreserializer<T, false>&) : _cached_size(-1) {}
VectorRefPreserializer& operator=(const VectorRefPreserializer<T, false>&) { _cached_size = -1; return *this; }
VectorRefPreserializer(const VectorRefPreserializer<T, VecSerStrategy::FlatBuffers>&) : _cached_size(-1) {}
VectorRefPreserializer& operator=(const VectorRefPreserializer<T, VecSerStrategy::FlatBuffers>&) {
_cached_size = -1;
return *this;
}
void invalidate() { _cached_size = -1; }
void add(const T& item) {
@ -865,21 +873,24 @@ struct VectorRefPreserializer<T, true> {
}
};
template <class T, bool StringSerialized = false>
class VectorRef : public ComposedIdentifier<T, 0x8>, public VectorRefPreserializer<T, StringSerialized> {
using VPS = VectorRefPreserializer<T, StringSerialized>;
friend class VectorRef<T, !StringSerialized>;
template <class T, VecSerStrategy SerStrategy = VecSerStrategy::FlatBuffers>
class VectorRef : public ComposedIdentifier<T, 0x8>, public VectorRefPreserializer<T, SerStrategy> {
using VPS = VectorRefPreserializer<T, SerStrategy>;
friend class VectorRef<T, SerStrategy == VecSerStrategy::FlatBuffers ? VecSerStrategy::String
: VecSerStrategy::FlatBuffers>;
public:
using value_type = T;
static_assert(!StringSerialized || string_serialized_traits<T>::value);
static_assert(SerStrategy == VecSerStrategy::FlatBuffers || string_serialized_traits<T>::value);
// T must be trivially destructible (and copyable)!
VectorRef() : data(0), m_size(0), m_capacity(0) {}
template<bool b2>
VectorRef(const VectorRef<T, b2>& other) : VPS(other), data(other.data), m_size(other.m_size), m_capacity(other.m_capacity) {}
template <bool b2>
VectorRef& operator=(const VectorRef<T, b2>& other) {
template <VecSerStrategy S>
VectorRef(const VectorRef<T, S>& other)
: VPS(other), data(other.data), m_size(other.m_size), m_capacity(other.m_capacity) {}
template <VecSerStrategy S>
VectorRef& operator=(const VectorRef<T, S>& other) {
*static_cast<VPS*>(this) = other;
data = other.data;
m_size = other.m_size;
@ -888,7 +899,7 @@ public:
}
// Arena constructor for non-Ref types, identified by memcpy_able
template <class T2 = T, bool S>
template <class T2 = T, VecSerStrategy S>
VectorRef(Arena& p, const VectorRef<T, S>& toCopy, typename std::enable_if<memcpy_able<T2>::value, int>::type = 0)
: VPS(toCopy), data((T*)new (p) uint8_t[sizeof(T) * toCopy.size()]), m_size(toCopy.size()),
m_capacity(toCopy.size()) {
@ -896,7 +907,7 @@ public:
}
// Arena constructor for Ref types, which must have an Arena constructor
template <class T2 = T, bool S>
template <class T2 = T, VecSerStrategy S>
VectorRef(Arena& p, const VectorRef<T, S>& toCopy, typename std::enable_if<!memcpy_able<T2>::value, int>::type = 0)
: VPS(), data((T*)new (p) uint8_t[sizeof(T) * toCopy.size()]), m_size(toCopy.size()), m_capacity(toCopy.size()) {
for (int i = 0; i < m_size; i++) {
@ -907,11 +918,11 @@ public:
VectorRef(T* data, int size) : data(data), m_size(size), m_capacity(size) {}
VectorRef(T* data, int size, int capacity) : data(data), m_size(size), m_capacity(capacity) {}
//VectorRef( const VectorRef<T>& toCopy ) : data( toCopy.data ), m_size( toCopy.m_size ), m_capacity( toCopy.m_capacity ) {}
//VectorRef<T>& operator=( const VectorRef<T>& );
// VectorRef( const VectorRef<T>& toCopy ) : data( toCopy.data ), m_size( toCopy.m_size ), m_capacity(
// toCopy.m_capacity ) {} VectorRef<T>& operator=( const VectorRef<T>& );
template<bool S = StringSerialized>
typename std::enable_if<S, uint32_t>::type serializedSize() const {
template <VecSerStrategy S = SerStrategy>
typename std::enable_if<S == VecSerStrategy::String, uint32_t>::type serializedSize() const {
uint32_t result = sizeof(uint32_t);
string_serialized_traits<T> t;
if (VPS::_cached_size >= 0) {
@ -935,25 +946,41 @@ public:
std::reverse_iterator<const T*> rbegin() const { return std::reverse_iterator<const T*>(end()); }
std::reverse_iterator<const T*> rend() const { return std::reverse_iterator<const T*>(begin()); }
template<bool S = StringSerialized>
typename std::enable_if<!S, VectorRef>::type slice(int begin, int end) const { return VectorRef(data+begin, end-begin); }
template <VecSerStrategy S = SerStrategy>
typename std::enable_if<S == VecSerStrategy::FlatBuffers, VectorRef>::type slice(int begin, int end) const {
return VectorRef(data + begin, end - begin);
}
template<bool S>
template <VecSerStrategy S>
bool operator==(VectorRef<T, S> const& rhs) const {
if (size() != rhs.size()) return false;
for (int i = 0; i < m_size; i++)
if ( (*this)[i] != rhs[i] )
return false;
if ((*this)[i] != rhs[i]) return false;
return true;
}
// Warning: Do not mutate a VectorRef that has previously been copy constructed or assigned,
// since copies will share data
T* begin() { VPS::invalidate(); return data; }
T* end() { VPS::invalidate(); return data + m_size; }
T& front() { VPS::invalidate(); return *begin(); }
T& back() { VPS::invalidate(); return end()[-1]; }
T& operator[](int i) { VPS::invalidate(); return data[i]; }
T* begin() {
VPS::invalidate();
return data;
}
T* end() {
VPS::invalidate();
return data + m_size;
}
T& front() {
VPS::invalidate();
return *begin();
}
T& back() {
VPS::invalidate();
return end()[-1];
}
T& operator[](int i) {
VPS::invalidate();
return data[i];
}
void push_back(Arena& p, const T& value) {
if (m_size + 1 > m_capacity) reallocate(p, m_size + 1);
auto ptr = new (&data[m_size]) T(value);
@ -982,7 +1009,10 @@ public:
}
m_size += count;
}
void pop_back() { VPS::remove(back()); m_size--; }
void pop_back() {
VPS::remove(back());
m_size--;
}
void pop_front(int count) {
VPS::invalidate();
@ -1014,21 +1044,15 @@ public:
// expectedSize() for Ref types, which must in turn have expectedSize() implemented.
template <class T2 = T>
typename std::enable_if<!memcpy_able<T2>::value, size_t>::type expectedSize() const
{
typename std::enable_if<!memcpy_able<T2>::value, size_t>::type expectedSize() const {
size_t t = sizeof(T) * m_size;
for(int i=0; i<m_size; i++)
t += data[i].expectedSize();
for (int i = 0; i < m_size; i++) t += data[i].expectedSize();
return t;
}
int capacity() const {
return m_capacity;
}
int capacity() const { return m_capacity; }
void extendUnsafeNoReallocNoInit(int amount) {
m_size += amount;
}
void extendUnsafeNoReallocNoInit(int amount) { m_size += amount; }
private:
T* data;
@ -1063,8 +1087,8 @@ struct Traceable<VectorRef<T>> {
}
};
template <class Archive, class T, bool b>
inline void load( Archive& ar, VectorRef<T, b>& value ) {
template <class Archive, class T, VecSerStrategy S>
inline void load( Archive& ar, VectorRef<T, S>& value ) {
// FIXME: range checking for length, here and in other serialize code
uint32_t length;
ar >> length;
@ -1074,8 +1098,8 @@ inline void load( Archive& ar, VectorRef<T, b>& value ) {
for(uint32_t i=0; i<length; i++)
ar >> value[i];
}
template <class Archive, class T, bool b>
inline void save( Archive& ar, const VectorRef<T, b>& value ) {
template <class Archive, class T, VecSerStrategy S>
inline void save( Archive& ar, const VectorRef<T, S>& value ) {
uint32_t length = value.size();
ar << length;
for(uint32_t i=0; i<length; i++)
@ -1083,7 +1107,7 @@ inline void save( Archive& ar, const VectorRef<T, b>& value ) {
}
template <class T>
struct vector_like_traits<VectorRef<T, false>> : std::true_type {
struct vector_like_traits<VectorRef<T, VecSerStrategy::FlatBuffers>> : std::true_type {
using Vec = VectorRef<T>;
using value_type = typename Vec::value_type;
using iterator = const T*;
@ -1105,8 +1129,8 @@ struct vector_like_traits<VectorRef<T, false>> : std::true_type {
};
template <class V>
struct dynamic_size_traits<VectorRef<V, true>> : std::true_type {
using T = VectorRef<V, true>;
struct dynamic_size_traits<VectorRef<V, VecSerStrategy::String>> : std::true_type {
using T = VectorRef<V, VecSerStrategy::String>;
// May be called multiple times during one serialization
template <class Context>
static size_t size(const T& t, Context&) {