Working on delta streaming.

This commit is contained in:
Andrzej Kapolka 2014-03-18 13:14:21 -07:00
parent a4cc15a2cd
commit 24b2da1c0d
5 changed files with 88 additions and 3 deletions

View file

@ -865,6 +865,21 @@ QVariant TypeReader::read(Bitstream& in) const {
return object;
}
void TypeReader::readDelta(Bitstream& in, QVariant& object, const QVariant& reference) const {
if (_exactMatch) {
_streamer->readDelta(in, object, reference);
return;
}
if (_valueReader) {
// TODO: collection deltas
} else {
foreach (const FieldReader& field, _fields) {
field.readDelta(in, _streamer, object, reference);
}
}
}
bool TypeReader::matchesExactly(const TypeStreamer* streamer) const {
return _exactMatch && _streamer == streamer;
}
@ -885,6 +900,10 @@ void FieldReader::read(Bitstream& in, const TypeStreamer* streamer, QVariant& ob
}
}
void FieldReader::readDelta(Bitstream& in, const TypeStreamer* streamer, QVariant& object, const QVariant& reference) const {
// TODO: field delta
}
ObjectReader::ObjectReader(const QByteArray& className, const QMetaObject* metaObject,
const QVector<PropertyReader>& properties) :
_className(className),

View file

@ -268,6 +268,9 @@ public:
/// Removes a shared object from the read mappings.
void clearSharedObject(int id);
template<class T> void writeDelta(const T& value, const T& reference);
template<class T> void readDelta(T& value, const T& reference);
Bitstream& operator<<(bool value);
Bitstream& operator>>(bool& value);
@ -378,6 +381,23 @@ private:
static QVector<PropertyReader> getPropertyReaders(const QMetaObject* metaObject);
};
template<class T> inline void Bitstream::writeDelta(const T& value, const T& reference) {
if (value == reference) {
*this << false;
} else {
*this << true;
*this << value;
}
}
template<class T> inline void Bitstream::readDelta(T& value, const T& reference) {
bool changed;
*this >> changed;
if (changed) {
*this >> value;
}
}
template<class T> inline Bitstream& Bitstream::operator<<(const QList<T>& list) {
*this << list.size();
foreach (const T& entry, list) {
@ -458,6 +478,7 @@ public:
const TypeStreamer* getStreamer() const { return _streamer; }
QVariant read(Bitstream& in) const;
void readDelta(Bitstream& in, QVariant& object, const QVariant& reference) const;
bool matchesExactly(const TypeStreamer* streamer) const;
@ -486,7 +507,8 @@ public:
int getIndex() const { return _index; }
void read(Bitstream& in, const TypeStreamer* streamer, QVariant& object) const;
void readDelta(Bitstream& in, const TypeStreamer* streamer, QVariant& object, const QVariant& reference) const;
private:
TypeReader _reader;
@ -565,6 +587,9 @@ public:
virtual void write(Bitstream& out, const QVariant& value) const = 0;
virtual QVariant read(Bitstream& in) const = 0;
virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const = 0;
virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const = 0;
virtual const QVector<MetaField>& getMetaFields() const;
virtual int getFieldIndex(const QByteArray& name) const;
virtual void setField(int index, QVariant& object, const QVariant& value) const;
@ -590,6 +615,10 @@ public:
virtual void write(Bitstream& out, const QVariant& value) const { out << value.value<T>(); }
virtual QVariant read(Bitstream& in) const { T value; in >> value; return QVariant::fromValue(value); }
virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const {
out.writeDelta(value.value<T>(), reference.value<T>()); }
virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const {
in.readDelta(*static_cast<T*>(value.data()), reference.value<T>()); }
};
/// A streamer for types compiled by mtc.
@ -652,6 +681,8 @@ public:
#define DECLARE_STREAMABLE_METATYPE(X) Q_DECLARE_METATYPE(X) \
Bitstream& operator<<(Bitstream& out, const X& obj); \
Bitstream& operator>>(Bitstream& in, X& obj); \
template<> void Bitstream::writeDelta(const X& value, const X& reference); \
template<> void Bitstream::readDelta(X& value, const X& reference); \
bool operator==(const X& first, const X& second); \
bool operator!=(const X& first, const X& second); \
static const int* _TypePtr##X = &X::Type;
@ -659,6 +690,8 @@ public:
#define DECLARE_STREAMABLE_METATYPE(X) Q_DECLARE_METATYPE(X) \
Bitstream& operator<<(Bitstream& out, const X& obj); \
Bitstream& operator>>(Bitstream& in, X& obj); \
template<> void Bitstream::writeDelta(const X& value, const X& reference); \
template<> void Bitstream::readDelta(X& value, const X& reference); \
bool operator==(const X& first, const X& second); \
bool operator!=(const X& first, const X& second); \
__attribute__((unused)) static const int* _TypePtr##X = &X::Type;
@ -667,6 +700,8 @@ public:
#define DECLARE_STREAMABLE_METATYPE(X) Q_DECLARE_METATYPE(X) \
Bitstream& operator<<(Bitstream& out, const X& obj); \
Bitstream& operator>>(Bitstream& in, X& obj); \
template<> void Bitstream::writeDelta(const X& value, const X& reference); \
template<> void Bitstream::readDelta(X& value, const X& reference); \
bool operator==(const X& first, const X& second); \
bool operator!=(const X& first, const X& second); \
static const int* _TypePtr##X = &X::Type; \

View file

@ -37,7 +37,7 @@ void SharedObject::decrementReferenceCount() {
}
}
SharedObject* SharedObject::clone() const {
SharedObject* SharedObject::clone(bool withID) const {
// default behavior is to make a copy using the no-arg constructor and copy the stored properties
const QMetaObject* metaObject = this->metaObject();
SharedObject* newObject = static_cast<SharedObject*>(metaObject->newInstance());
@ -50,6 +50,9 @@ SharedObject* SharedObject::clone() const {
foreach (const QByteArray& propertyName, dynamicPropertyNames()) {
newObject->setProperty(propertyName, property(propertyName));
}
if (withID) {
newObject->setID(_id);
}
return newObject;
}
@ -91,6 +94,11 @@ void SharedObject::dump(QDebug debug) const {
}
}
void SharedObject::setID(int id) {
_weakHash.remove(_id);
_weakHash.insert(_id = id, this);
}
int SharedObject::_lastID = 0;
WeakSharedObjectHash SharedObject::_weakHash;

View file

@ -47,7 +47,8 @@ public:
void decrementReferenceCount();
/// Creates a new clone of this object.
virtual SharedObject* clone() const;
/// \param withID if true, give the clone the same ID as this object
virtual SharedObject* clone(bool withID = false) const;
/// Tests this object for equality with another.
virtual bool equals(const SharedObject* other) const;
@ -57,6 +58,8 @@ public:
private:
void setID(int id);
int _id;
int _remoteID;
int _referenceCount;

View file

@ -172,6 +172,26 @@ void generateOutput (QTextStream& out, const QList<Streamable>& streamables) {
out << " return in;\n";
out << "}\n";
out << "template<> void Bitstream::writeDelta(const " << name << "& value, const " << name << "& reference) {\n";
foreach (const QString& base, str.clazz.bases) {
out << " writeDelta(static_cast<const " << base << "&>(value), static_cast<const " <<
base << "&>(reference));\n";
}
foreach (const Field& field, str.fields) {
out << " writeDelta(value." << field.name << ", reference." << field.name << ");\n";
}
out << "}\n";
out << "template<> void Bitstream::readDelta(" << name << "& value, const " << name << "& reference) {\n";
foreach (const QString& base, str.clazz.bases) {
out << " readDelta(static_cast<" << base << "&>(value), static_cast<const " <<
base << "&>(reference));\n";
}
foreach (const Field& field, str.fields) {
out << " readDelta(value." << field.name << ", reference." << field.name << ");\n";
}
out << "}\n";
out << "bool operator==(const " << name << "& first, const " << name << "& second) {\n";
if (str.clazz.bases.isEmpty() && str.fields.isEmpty()) {
out << " return true";