Pass type as param to VectorRef instead of bool
This commit is contained in:
parent
707b29cbcc
commit
54416f46fd
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
182
flow/Arena.h
182
flow/Arena.h
|
@ -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++) {
|
||||
|
@ -905,13 +916,13 @@ 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(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>& );
|
||||
|
||||
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) {
|
||||
|
@ -932,59 +943,78 @@ public:
|
|||
bool empty() const { return m_size == 0; }
|
||||
const T& operator[](int i) const { return data[i]; }
|
||||
|
||||
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() ); }
|
||||
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>
|
||||
bool operator == ( VectorRef<T, S> const& rhs ) const {
|
||||
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;
|
||||
for (int i = 0; i < m_size; i++)
|
||||
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]; }
|
||||
void push_back( Arena& p, const T& value ) {
|
||||
if (m_size + 1 > m_capacity) reallocate(p, m_size+1);
|
||||
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);
|
||||
VPS::add(*ptr);
|
||||
m_size++;
|
||||
}
|
||||
// invokes the "Deep copy constructor" T(Arena&, const T&) moving T entirely into arena
|
||||
void push_back_deep( Arena& p, const T& value ) {
|
||||
if (m_size + 1 > m_capacity) reallocate(p, m_size+1);
|
||||
void push_back_deep(Arena& p, const T& value) {
|
||||
if (m_size + 1 > m_capacity) reallocate(p, m_size + 1);
|
||||
auto ptr = new (&data[m_size]) T(p, value);
|
||||
VPS::add(*ptr);
|
||||
m_size++;
|
||||
}
|
||||
void append( Arena& p, const T* begin, int count ) {
|
||||
void append(Arena& p, const T* begin, int count) {
|
||||
if (m_size + count > m_capacity) reallocate(p, m_size + count);
|
||||
VPS::invalidate();
|
||||
memcpy( data+m_size, begin, sizeof(T)*count );
|
||||
memcpy(data + m_size, begin, sizeof(T) * count);
|
||||
m_size += count;
|
||||
}
|
||||
template <class It>
|
||||
void append_deep( Arena& p, It begin, int count ) {
|
||||
void append_deep(Arena& p, It begin, int count) {
|
||||
if (m_size + count > m_capacity) reallocate(p, m_size + count);
|
||||
for(int i=0; i<count; i++) {
|
||||
auto ptr = new (&data[m_size+i]) T( p, *begin++ );
|
||||
for (int i = 0; i < count; i++) {
|
||||
auto ptr = new (&data[m_size + i]) T(p, *begin++);
|
||||
VPS::add(*ptr);
|
||||
}
|
||||
m_size += count;
|
||||
}
|
||||
void pop_back() { VPS::remove(back()); m_size--; }
|
||||
void pop_back() {
|
||||
VPS::remove(back());
|
||||
m_size--;
|
||||
}
|
||||
|
||||
void pop_front( int count ) {
|
||||
void pop_front(int count) {
|
||||
VPS::invalidate();
|
||||
count = std::min(m_size, count);
|
||||
|
||||
|
@ -993,52 +1023,46 @@ public:
|
|||
m_capacity -= count;
|
||||
}
|
||||
|
||||
void resize( Arena& p, int size ) {
|
||||
void resize(Arena& p, int size) {
|
||||
if (size > m_capacity) reallocate(p, size);
|
||||
for(int i=m_size; i<size; i++) {
|
||||
for (int i = m_size; i < size; i++) {
|
||||
auto ptr = new (&data[i]) T();
|
||||
VPS::add(*ptr);
|
||||
}
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void reserve( Arena& p, int size ) {
|
||||
void reserve(Arena& p, int size) {
|
||||
if (size > m_capacity) reallocate(p, size);
|
||||
}
|
||||
|
||||
// expectedSize() for non-Ref types, identified by memcpy_able
|
||||
template<class T2 = T>
|
||||
template <class T2 = T>
|
||||
typename std::enable_if<memcpy_able<T2>::value, size_t>::type expectedSize() const {
|
||||
return sizeof(T)*m_size;
|
||||
return sizeof(T) * m_size;
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
size_t t = sizeof(T)*m_size;
|
||||
for(int i=0; i<m_size; i++)
|
||||
t += data[i].expectedSize();
|
||||
template <class T2 = T>
|
||||
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();
|
||||
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;
|
||||
int m_size, m_capacity;
|
||||
|
||||
void reallocate(Arena& p, int requiredCapacity) {
|
||||
requiredCapacity = std::max( m_capacity*2, requiredCapacity );
|
||||
requiredCapacity = std::max(m_capacity * 2, requiredCapacity);
|
||||
// SOMEDAY: Maybe we are right at the end of the arena and can expand cheaply
|
||||
T* newData = (T*)new (p) uint8_t[ requiredCapacity * sizeof(T) ];
|
||||
memcpy(newData, data, m_size*sizeof(T));
|
||||
T* newData = (T*)new (p) uint8_t[requiredCapacity * sizeof(T)];
|
||||
memcpy(newData, data, m_size * sizeof(T));
|
||||
data = newData;
|
||||
m_capacity = requiredCapacity;
|
||||
}
|
||||
|
@ -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&) {
|
||||
|
|
Loading…
Reference in New Issue