mirror of
https://github.com/overte-org/overte.git
synced 2025-07-29 10:20:54 +02:00
Revert complicated system of "soft" pointers, instead use hard references in
write mappings and listen for object destruction.
This commit is contained in:
parent
55dca45feb
commit
949e40a10e
6 changed files with 108 additions and 135 deletions
|
@ -168,19 +168,16 @@ void Bitstream::persistWriteMappings(const WriteMappings& mappings) {
|
||||||
_sharedObjectStreamer.persistTransientOffsets(mappings.sharedObjectOffsets);
|
_sharedObjectStreamer.persistTransientOffsets(mappings.sharedObjectOffsets);
|
||||||
|
|
||||||
// find out when shared objects are deleted in order to clear their mappings
|
// find out when shared objects are deleted in order to clear their mappings
|
||||||
for (QHash<SoftSharedObjectPointer, int>::const_iterator it = mappings.sharedObjectOffsets.constBegin();
|
for (QHash<SharedObjectPointer, int>::const_iterator it = mappings.sharedObjectOffsets.constBegin();
|
||||||
it != mappings.sharedObjectOffsets.constEnd(); it++) {
|
it != mappings.sharedObjectOffsets.constEnd(); it++) {
|
||||||
if (it.key()) {
|
if (it.key()) {
|
||||||
if (it.key()->getHardReferenceCount() > 0) {
|
connect(it.key().data(), SIGNAL(destroyed(QObject*)), SLOT(clearSharedObject(QObject*)));
|
||||||
connect(it.key().data(), SIGNAL(allHardReferencesCleared(QObject*)),
|
|
||||||
SLOT(clearSharedObject(QObject*)));
|
|
||||||
} else {
|
|
||||||
// invoke on a queued connection so as to run after any other mappings are persisted
|
|
||||||
QMetaObject::invokeMethod(this, "clearSharedObject", Qt::QueuedConnection,
|
|
||||||
Q_ARG(QObject*, it.key().data()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bitstream::persistAndResetWriteMappings() {
|
||||||
|
persistWriteMappings(getAndResetWriteMappings());
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitstream::ReadMappings Bitstream::getAndResetReadMappings() {
|
Bitstream::ReadMappings Bitstream::getAndResetReadMappings() {
|
||||||
|
@ -200,6 +197,10 @@ void Bitstream::persistReadMappings(const ReadMappings& mappings) {
|
||||||
_sharedObjectStreamer.persistTransientValues(mappings.sharedObjectValues);
|
_sharedObjectStreamer.persistTransientValues(mappings.sharedObjectValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bitstream::persistAndResetReadMappings() {
|
||||||
|
persistReadMappings(getAndResetReadMappings());
|
||||||
|
}
|
||||||
|
|
||||||
Bitstream& Bitstream::operator<<(bool value) {
|
Bitstream& Bitstream::operator<<(bool value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
_byte |= (1 << _position);
|
_byte |= (1 << _position);
|
||||||
|
@ -472,7 +473,7 @@ Bitstream& Bitstream::operator>(QScriptString& string) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitstream& Bitstream::operator<(const SoftSharedObjectPointer& object) {
|
Bitstream& Bitstream::operator<(const SharedObjectPointer& object) {
|
||||||
if (!object) {
|
if (!object) {
|
||||||
return *this << (int)0;
|
return *this << (int)0;
|
||||||
}
|
}
|
||||||
|
@ -505,7 +506,6 @@ Bitstream& Bitstream::operator>(SharedObjectPointer& object) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bitstream::clearSharedObject(QObject* object) {
|
void Bitstream::clearSharedObject(QObject* object) {
|
||||||
object->disconnect(this);
|
|
||||||
int id = _sharedObjectStreamer.takePersistentID(static_cast<SharedObject*>(object));
|
int id = _sharedObjectStreamer.takePersistentID(static_cast<SharedObject*>(object));
|
||||||
if (id != 0) {
|
if (id != 0) {
|
||||||
emit sharedObjectCleared(id);
|
emit sharedObjectCleared(id);
|
||||||
|
|
|
@ -55,26 +55,26 @@ private:
|
||||||
|
|
||||||
/// Provides a means to stream repeated values efficiently. The value is first streamed along with a unique ID. When
|
/// Provides a means to stream repeated values efficiently. The value is first streamed along with a unique ID. When
|
||||||
/// subsequently streamed, only the ID is sent.
|
/// subsequently streamed, only the ID is sent.
|
||||||
template<class K, class V = K> class RepeatedValueStreamer {
|
template<class T, class P = T> class RepeatedValueStreamer {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RepeatedValueStreamer(Bitstream& stream) : _stream(stream), _idStreamer(stream),
|
RepeatedValueStreamer(Bitstream& stream) : _stream(stream), _idStreamer(stream),
|
||||||
_lastPersistentID(0), _lastTransientOffset(0) { }
|
_lastPersistentID(0), _lastTransientOffset(0) { }
|
||||||
|
|
||||||
QHash<K, int> getAndResetTransientOffsets();
|
QHash<T, int> getAndResetTransientOffsets();
|
||||||
|
|
||||||
void persistTransientOffsets(const QHash<K, int>& transientOffsets);
|
void persistTransientOffsets(const QHash<T, int>& transientOffsets);
|
||||||
|
|
||||||
QHash<int, V> getAndResetTransientValues();
|
QHash<int, T> getAndResetTransientValues();
|
||||||
|
|
||||||
void persistTransientValues(const QHash<int, V>& transientValues);
|
void persistTransientValues(const QHash<int, T>& transientValues);
|
||||||
|
|
||||||
int takePersistentID(K value) { return _persistentIDs.take(value); }
|
int takePersistentID(P value) { return _persistentIDs.take(value); }
|
||||||
|
|
||||||
void removePersistentValue(int id) { _persistentValues.remove(id); }
|
void removePersistentValue(int id) { _persistentIDs.remove(_persistentValues.take(id)); }
|
||||||
|
|
||||||
RepeatedValueStreamer& operator<<(K value);
|
RepeatedValueStreamer& operator<<(T value);
|
||||||
RepeatedValueStreamer& operator>>(V& value);
|
RepeatedValueStreamer& operator>>(T& value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -82,24 +82,24 @@ private:
|
||||||
IDStreamer _idStreamer;
|
IDStreamer _idStreamer;
|
||||||
int _lastPersistentID;
|
int _lastPersistentID;
|
||||||
int _lastTransientOffset;
|
int _lastTransientOffset;
|
||||||
QHash<K, int> _persistentIDs;
|
QHash<P, int> _persistentIDs;
|
||||||
QHash<K, int> _transientOffsets;
|
QHash<T, int> _transientOffsets;
|
||||||
QHash<int, V> _persistentValues;
|
QHash<int, T> _persistentValues;
|
||||||
QHash<int, V> _transientValues;
|
QHash<int, T> _transientValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class K, class V> inline QHash<K, int> RepeatedValueStreamer<K, V>::getAndResetTransientOffsets() {
|
template<class T, class P> inline QHash<T, int> RepeatedValueStreamer<T, P>::getAndResetTransientOffsets() {
|
||||||
QHash<K, int> transientOffsets;
|
QHash<T, int> transientOffsets;
|
||||||
_transientOffsets.swap(transientOffsets);
|
_transientOffsets.swap(transientOffsets);
|
||||||
_lastTransientOffset = 0;
|
_lastTransientOffset = 0;
|
||||||
_idStreamer.setBitsFromValue(_lastPersistentID);
|
_idStreamer.setBitsFromValue(_lastPersistentID);
|
||||||
return transientOffsets;
|
return transientOffsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class K, class V> inline void RepeatedValueStreamer<K, V>::persistTransientOffsets(
|
template<class T, class P> inline void RepeatedValueStreamer<T, P>::persistTransientOffsets(
|
||||||
const QHash<K, int>& transientOffsets) {
|
const QHash<T, int>& transientOffsets) {
|
||||||
int oldLastPersistentID = _lastPersistentID;
|
int oldLastPersistentID = _lastPersistentID;
|
||||||
for (typename QHash<K, int>::const_iterator it = transientOffsets.constBegin(); it != transientOffsets.constEnd(); it++) {
|
for (typename QHash<T, int>::const_iterator it = transientOffsets.constBegin(); it != transientOffsets.constEnd(); it++) {
|
||||||
int& id = _persistentIDs[it.key()];
|
int& id = _persistentIDs[it.key()];
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
id = oldLastPersistentID + it.value();
|
id = oldLastPersistentID + it.value();
|
||||||
|
@ -109,17 +109,17 @@ template<class K, class V> inline void RepeatedValueStreamer<K, V>::persistTrans
|
||||||
_idStreamer.setBitsFromValue(_lastPersistentID);
|
_idStreamer.setBitsFromValue(_lastPersistentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class K, class V> inline QHash<int, V> RepeatedValueStreamer<K, V>::getAndResetTransientValues() {
|
template<class T, class P> inline QHash<int, T> RepeatedValueStreamer<T, P>::getAndResetTransientValues() {
|
||||||
QHash<int, V> transientValues;
|
QHash<int, T> transientValues;
|
||||||
_transientValues.swap(transientValues);
|
_transientValues.swap(transientValues);
|
||||||
_idStreamer.setBitsFromValue(_lastPersistentID);
|
_idStreamer.setBitsFromValue(_lastPersistentID);
|
||||||
return transientValues;
|
return transientValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class K, class V> inline void RepeatedValueStreamer<K, V>::persistTransientValues(
|
template<class T, class P> inline void RepeatedValueStreamer<T, P>::persistTransientValues(
|
||||||
const QHash<int, V>& transientValues) {
|
const QHash<int, T>& transientValues) {
|
||||||
int oldLastPersistentID = _lastPersistentID;
|
int oldLastPersistentID = _lastPersistentID;
|
||||||
for (typename QHash<int, V>::const_iterator it = transientValues.constBegin(); it != transientValues.constEnd(); it++) {
|
for (typename QHash<int, T>::const_iterator it = transientValues.constBegin(); it != transientValues.constEnd(); it++) {
|
||||||
int& id = _persistentIDs[it.value()];
|
int& id = _persistentIDs[it.value()];
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
id = oldLastPersistentID + it.key();
|
id = oldLastPersistentID + it.key();
|
||||||
|
@ -130,7 +130,7 @@ template<class K, class V> inline void RepeatedValueStreamer<K, V>::persistTrans
|
||||||
_idStreamer.setBitsFromValue(_lastPersistentID);
|
_idStreamer.setBitsFromValue(_lastPersistentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class K, class V> inline RepeatedValueStreamer<K, V>& RepeatedValueStreamer<K, V>::operator<<(K value) {
|
template<class T, class P> inline RepeatedValueStreamer<T, P>& RepeatedValueStreamer<T, P>::operator<<(T value) {
|
||||||
int id = _persistentIDs.value(value);
|
int id = _persistentIDs.value(value);
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
int& offset = _transientOffsets[value];
|
int& offset = _transientOffsets[value];
|
||||||
|
@ -147,7 +147,7 @@ template<class K, class V> inline RepeatedValueStreamer<K, V>& RepeatedValueStre
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class K, class V> inline RepeatedValueStreamer<K, V>& RepeatedValueStreamer<K, V>::operator>>(V& value) {
|
template<class T, class P> inline RepeatedValueStreamer<T, P>& RepeatedValueStreamer<T, P>::operator>>(T& value) {
|
||||||
int id;
|
int id;
|
||||||
_idStreamer >> id;
|
_idStreamer >> id;
|
||||||
if (id <= _lastPersistentID) {
|
if (id <= _lastPersistentID) {
|
||||||
|
@ -155,7 +155,7 @@ template<class K, class V> inline RepeatedValueStreamer<K, V>& RepeatedValueStre
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
int offset = id - _lastPersistentID;
|
int offset = id - _lastPersistentID;
|
||||||
typename QHash<int, V>::iterator it = _transientValues.find(offset);
|
typename QHash<int, T>::iterator it = _transientValues.find(offset);
|
||||||
if (it == _transientValues.end()) {
|
if (it == _transientValues.end()) {
|
||||||
_stream > value;
|
_stream > value;
|
||||||
_transientValues.insert(offset, value);
|
_transientValues.insert(offset, value);
|
||||||
|
@ -179,7 +179,7 @@ public:
|
||||||
QHash<const TypeStreamer*, int> typeStreamerOffsets;
|
QHash<const TypeStreamer*, int> typeStreamerOffsets;
|
||||||
QHash<AttributePointer, int> attributeOffsets;
|
QHash<AttributePointer, int> attributeOffsets;
|
||||||
QHash<QScriptString, int> scriptStringOffsets;
|
QHash<QScriptString, int> scriptStringOffsets;
|
||||||
QHash<SoftSharedObjectPointer, int> sharedObjectOffsets;
|
QHash<SharedObjectPointer, int> sharedObjectOffsets;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ReadMappings {
|
class ReadMappings {
|
||||||
|
@ -230,12 +230,18 @@ public:
|
||||||
/// Persists a set of write mappings recorded earlier.
|
/// Persists a set of write mappings recorded earlier.
|
||||||
void persistWriteMappings(const WriteMappings& mappings);
|
void persistWriteMappings(const WriteMappings& mappings);
|
||||||
|
|
||||||
|
/// Immediately persists and resets the write mappings.
|
||||||
|
void persistAndResetWriteMappings();
|
||||||
|
|
||||||
/// Returns the set of transient mappings gathered during reading and resets them.
|
/// Returns the set of transient mappings gathered during reading and resets them.
|
||||||
ReadMappings getAndResetReadMappings();
|
ReadMappings getAndResetReadMappings();
|
||||||
|
|
||||||
/// Persists a set of read mappings recorded earlier.
|
/// Persists a set of read mappings recorded earlier.
|
||||||
void persistReadMappings(const ReadMappings& mappings);
|
void persistReadMappings(const ReadMappings& mappings);
|
||||||
|
|
||||||
|
/// Immediately persists and resets the read mappings.
|
||||||
|
void persistAndResetReadMappings();
|
||||||
|
|
||||||
/// Removes a shared object from the read mappings.
|
/// Removes a shared object from the read mappings.
|
||||||
void clearSharedObject(int id) { _sharedObjectStreamer.removePersistentValue(id); }
|
void clearSharedObject(int id) { _sharedObjectStreamer.removePersistentValue(id); }
|
||||||
|
|
||||||
|
@ -308,7 +314,7 @@ public:
|
||||||
Bitstream& operator<(const QScriptString& string);
|
Bitstream& operator<(const QScriptString& string);
|
||||||
Bitstream& operator>(QScriptString& string);
|
Bitstream& operator>(QScriptString& string);
|
||||||
|
|
||||||
Bitstream& operator<(const SoftSharedObjectPointer& object);
|
Bitstream& operator<(const SharedObjectPointer& object);
|
||||||
Bitstream& operator>(SharedObjectPointer& object);
|
Bitstream& operator>(SharedObjectPointer& object);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -331,7 +337,7 @@ private:
|
||||||
RepeatedValueStreamer<const TypeStreamer*> _typeStreamerStreamer;
|
RepeatedValueStreamer<const TypeStreamer*> _typeStreamerStreamer;
|
||||||
RepeatedValueStreamer<AttributePointer> _attributeStreamer;
|
RepeatedValueStreamer<AttributePointer> _attributeStreamer;
|
||||||
RepeatedValueStreamer<QScriptString> _scriptStringStreamer;
|
RepeatedValueStreamer<QScriptString> _scriptStringStreamer;
|
||||||
RepeatedValueStreamer<SoftSharedObjectPointer, SharedObjectPointer> _sharedObjectStreamer;
|
RepeatedValueStreamer<SharedObjectPointer, SharedObject*> _sharedObjectStreamer;
|
||||||
|
|
||||||
QHash<int, QPointer<SharedObject> > _transientSharedObjects;
|
QHash<int, QPointer<SharedObject> > _transientSharedObjects;
|
||||||
|
|
||||||
|
|
|
@ -587,6 +587,7 @@ void ReliableChannel::sendMessage(const QVariant& message) {
|
||||||
_dataStream << (quint32)0;
|
_dataStream << (quint32)0;
|
||||||
_bitstream << message;
|
_bitstream << message;
|
||||||
_bitstream.flush();
|
_bitstream.flush();
|
||||||
|
_bitstream.persistAndResetWriteMappings();
|
||||||
|
|
||||||
quint32 length = _buffer.pos() - placeholder;
|
quint32 length = _buffer.pos() - placeholder;
|
||||||
_buffer.writeBytes(placeholder, sizeof(quint32), (const char*)&length);
|
_buffer.writeBytes(placeholder, sizeof(quint32), (const char*)&length);
|
||||||
|
@ -745,6 +746,7 @@ void ReliableChannel::readData(QDataStream& in) {
|
||||||
QVariant message;
|
QVariant message;
|
||||||
_bitstream >> message;
|
_bitstream >> message;
|
||||||
_bitstream.reset();
|
_bitstream.reset();
|
||||||
|
_bitstream.persistAndResetReadMappings();
|
||||||
emit receivedMessage(message);
|
emit receivedMessage(message);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,29 +18,15 @@
|
||||||
|
|
||||||
REGISTER_META_OBJECT(SharedObject)
|
REGISTER_META_OBJECT(SharedObject)
|
||||||
|
|
||||||
static int sharedObjectPointerMetaTypeId = qRegisterMetaType<SharedObjectPointer>();
|
SharedObject::SharedObject() : _id(++_lastID), _referenceCount(0) {
|
||||||
static int softSharedObjectPointerMetaTypeId = qRegisterMetaType<SoftSharedObjectPointer>();
|
|
||||||
|
|
||||||
SharedObject::SharedObject() :
|
|
||||||
_id(++_lastID),
|
|
||||||
_hardReferenceCount(0),
|
|
||||||
_softReferenceCount(0) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedObject::decrementHardReferenceCount() {
|
void SharedObject::incrementReferenceCount() {
|
||||||
_hardReferenceCount--;
|
_referenceCount++;
|
||||||
if (_hardReferenceCount == 0) {
|
|
||||||
if (_softReferenceCount == 0) {
|
|
||||||
delete this;
|
|
||||||
} else {
|
|
||||||
emit allHardReferencesCleared(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedObject::decrementSoftReferenceCount() {
|
void SharedObject::decrementReferenceCount() {
|
||||||
_softReferenceCount--;
|
if (--_referenceCount == 0) {
|
||||||
if (_hardReferenceCount == 0 && _softReferenceCount == 0) {
|
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,13 +48,13 @@ SharedObject* SharedObject::clone() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SharedObject::equals(const SharedObject* other) const {
|
bool SharedObject::equals(const SharedObject* other) const {
|
||||||
// default behavior is to compare the properties
|
|
||||||
if (!other) {
|
if (!other) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (other == this) {
|
if (other == this) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// default behavior is to compare the properties
|
||||||
const QMetaObject* metaObject = this->metaObject();
|
const QMetaObject* metaObject = this->metaObject();
|
||||||
if (metaObject != other->metaObject()) {
|
if (metaObject != other->metaObject()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -27,13 +27,9 @@ public:
|
||||||
|
|
||||||
int getID() { return _id; }
|
int getID() { return _id; }
|
||||||
|
|
||||||
int getHardReferenceCount() const { return _hardReferenceCount; }
|
int getReferenceCount() const { return _referenceCount; }
|
||||||
|
void incrementReferenceCount();
|
||||||
void incrementHardReferenceCount() { _hardReferenceCount++; }
|
void decrementReferenceCount();
|
||||||
void decrementHardReferenceCount();
|
|
||||||
|
|
||||||
void incrementSoftReferenceCount() { _softReferenceCount++; }
|
|
||||||
void decrementSoftReferenceCount();
|
|
||||||
|
|
||||||
/// Creates a new clone of this object.
|
/// Creates a new clone of this object.
|
||||||
virtual SharedObject* clone() const;
|
virtual SharedObject* clone() const;
|
||||||
|
@ -44,31 +40,20 @@ public:
|
||||||
// Dumps the contents of this object to the debug output.
|
// Dumps the contents of this object to the debug output.
|
||||||
virtual void dump(QDebug debug = QDebug(QtDebugMsg)) const;
|
virtual void dump(QDebug debug = QDebug(QtDebugMsg)) const;
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
/// Emitted when only soft reference counts remain.
|
|
||||||
void allHardReferencesCleared(QObject* object);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int _id;
|
int _id;
|
||||||
int _hardReferenceCount;
|
int _referenceCount;
|
||||||
int _softReferenceCount;
|
|
||||||
|
|
||||||
static int _lastID;
|
static int _lastID;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (SharedObject::*SharedObjectFn)();
|
|
||||||
|
|
||||||
/// A pointer to a shared object.
|
/// A pointer to a shared object.
|
||||||
template<class T, SharedObjectFn Inc = &SharedObject::incrementHardReferenceCount,
|
template<class T> class SharedObjectPointerTemplate {
|
||||||
SharedObjectFn Dec = &SharedObject::decrementHardReferenceCount> class SharedObjectPointerTemplate {
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SharedObjectPointerTemplate(T* data = NULL);
|
SharedObjectPointerTemplate(T* data = NULL);
|
||||||
SharedObjectPointerTemplate(const SharedObjectPointerTemplate<T, Inc, Dec>& other);
|
SharedObjectPointerTemplate(const SharedObjectPointerTemplate<T>& other);
|
||||||
template<class X, SharedObjectFn Inc2, SharedObjectFn Dec2> SharedObjectPointerTemplate(
|
|
||||||
const SharedObjectPointerTemplate<X, Inc2, Dec2>& other);
|
|
||||||
~SharedObjectPointerTemplate();
|
~SharedObjectPointerTemplate();
|
||||||
|
|
||||||
T* data() const { return _data; }
|
T* data() const { return _data; }
|
||||||
|
@ -76,7 +61,7 @@ public:
|
||||||
/// "Detaches" this object, making a new copy if its reference count is greater than one.
|
/// "Detaches" this object, making a new copy if its reference count is greater than one.
|
||||||
bool detach();
|
bool detach();
|
||||||
|
|
||||||
void swap(SharedObjectPointerTemplate<T, Inc, Dec>& other) { qSwap(_data, other._data); }
|
void swap(SharedObjectPointerTemplate<T>& other) { qSwap(_data, other._data); }
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
@ -85,96 +70,86 @@ public:
|
||||||
T& operator*() const { return *_data; }
|
T& operator*() const { return *_data; }
|
||||||
T* operator->() const { return _data; }
|
T* operator->() const { return _data; }
|
||||||
|
|
||||||
template<class X> SharedObjectPointerTemplate<X, Inc, Dec> staticCast() const;
|
template<class X> SharedObjectPointerTemplate<X> staticCast() const;
|
||||||
|
|
||||||
SharedObjectPointerTemplate<T, Inc, Dec>& operator=(T* data);
|
SharedObjectPointerTemplate<T>& operator=(T* data);
|
||||||
SharedObjectPointerTemplate<T, Inc, Dec>& operator=(const SharedObjectPointerTemplate<T, Inc, Dec>& other) {
|
SharedObjectPointerTemplate<T>& operator=(const SharedObjectPointerTemplate<T>& other);
|
||||||
return *this = other.data(); }
|
|
||||||
template<class X, SharedObjectFn Inc2, SharedObjectFn Dec2> SharedObjectPointerTemplate<T, Inc, Dec>& operator=(
|
|
||||||
const SharedObjectPointerTemplate<X, Inc2, Dec2>& other) { return *this = other.data(); }
|
|
||||||
|
|
||||||
bool operator==(T* data) const { return _data == data; }
|
bool operator==(const SharedObjectPointerTemplate<T>& other) const { return _data == other._data; }
|
||||||
bool operator!=(T* data) const { return _data != data; }
|
bool operator!=(const SharedObjectPointerTemplate<T>& other) const { return _data != other._data; }
|
||||||
|
|
||||||
template<class X, SharedObjectFn Inc2, SharedObjectFn Dec2> bool operator==(
|
|
||||||
const SharedObjectPointerTemplate<X, Inc2, Dec2>& other) const { return _data == other.data(); }
|
|
||||||
template<class X, SharedObjectFn Inc2, SharedObjectFn Dec2> bool operator!=(
|
|
||||||
const SharedObjectPointerTemplate<X, Inc2, Dec2>& other) const { return _data != other.data(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
T* _data;
|
T* _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> inline
|
template<class T> inline SharedObjectPointerTemplate<T>::SharedObjectPointerTemplate(T* data) : _data(data) {
|
||||||
SharedObjectPointerTemplate<T, Inc, Dec>::SharedObjectPointerTemplate(T* data) : _data(data) {
|
|
||||||
if (_data) {
|
if (_data) {
|
||||||
(_data->*Inc)();
|
_data->incrementReferenceCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> inline
|
template<class T> inline SharedObjectPointerTemplate<T>::SharedObjectPointerTemplate(const SharedObjectPointerTemplate<T>& other) :
|
||||||
SharedObjectPointerTemplate<T, Inc, Dec>::SharedObjectPointerTemplate(
|
_data(other._data) {
|
||||||
const SharedObjectPointerTemplate<T, Inc, Dec>& other) : _data(other.data()) {
|
|
||||||
if (_data) {
|
if (_data) {
|
||||||
(_data->*Inc)();
|
_data->incrementReferenceCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> template<class X, SharedObjectFn Inc2, SharedObjectFn Dec2> inline
|
template<class T> inline SharedObjectPointerTemplate<T>::~SharedObjectPointerTemplate() {
|
||||||
SharedObjectPointerTemplate<T, Inc, Dec>::SharedObjectPointerTemplate(
|
|
||||||
const SharedObjectPointerTemplate<X, Inc2, Dec2>& other) : _data(other.data()) {
|
|
||||||
if (_data) {
|
if (_data) {
|
||||||
(_data->*Inc)();
|
_data->decrementReferenceCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> inline
|
template<class T> inline bool SharedObjectPointerTemplate<T>::detach() {
|
||||||
SharedObjectPointerTemplate<T, Inc, Dec>::~SharedObjectPointerTemplate() {
|
if (_data && _data->getReferenceCount() > 1) {
|
||||||
if (_data) {
|
_data->decrementReferenceCount();
|
||||||
(_data->*Dec)();
|
(_data = _data->clone())->incrementReferenceCount();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> inline bool SharedObjectPointerTemplate<T, Inc, Dec>::detach() {
|
|
||||||
if (_data && _data->getHardReferenceCount() > 1) {
|
|
||||||
(_data->*Dec)();
|
|
||||||
((_data = _data->clone())->*Inc)();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> inline void SharedObjectPointerTemplate<T, Inc, Dec>::reset() {
|
template<class T> inline void SharedObjectPointerTemplate<T>::reset() {
|
||||||
if (_data) {
|
if (_data) {
|
||||||
(_data->*Dec)();
|
_data->decrementReferenceCount();
|
||||||
}
|
}
|
||||||
_data = NULL;
|
_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> template<class X> inline
|
template<class T> template<class X> inline SharedObjectPointerTemplate<X> SharedObjectPointerTemplate<T>::staticCast() const {
|
||||||
SharedObjectPointerTemplate<X, Inc, Dec> SharedObjectPointerTemplate<T, Inc, Dec>::staticCast() const {
|
return SharedObjectPointerTemplate<X>(static_cast<X*>(_data));
|
||||||
return SharedObjectPointerTemplate<X, Inc, Dec>(static_cast<X*>(_data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> inline
|
template<class T> inline SharedObjectPointerTemplate<T>& SharedObjectPointerTemplate<T>::operator=(T* data) {
|
||||||
SharedObjectPointerTemplate<T, Inc, Dec>& SharedObjectPointerTemplate<T, Inc, Dec>::operator=(T* data) {
|
|
||||||
if (_data) {
|
if (_data) {
|
||||||
(_data->*Dec)();
|
_data->decrementReferenceCount();
|
||||||
}
|
}
|
||||||
if ((_data = data)) {
|
if ((_data = data)) {
|
||||||
(_data->*Inc)();
|
_data->incrementReferenceCount();
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec> uint qHash(
|
template<class T> inline SharedObjectPointerTemplate<T>& SharedObjectPointerTemplate<T>::operator=(
|
||||||
const SharedObjectPointerTemplate<T, Inc, Dec>& pointer, uint seed = 0) {
|
const SharedObjectPointerTemplate<T>& other) {
|
||||||
|
if (_data) {
|
||||||
|
_data->decrementReferenceCount();
|
||||||
|
}
|
||||||
|
if ((_data = other._data)) {
|
||||||
|
_data->incrementReferenceCount();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> uint qHash(const SharedObjectPointerTemplate<T>& pointer, uint seed = 0) {
|
||||||
return qHash(pointer.data(), seed);
|
return qHash(pointer.data(), seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, SharedObjectFn Inc, SharedObjectFn Dec, class X, SharedObjectFn Inc2, SharedObjectFn Dec2> bool equals(
|
template<class T, class X> bool equals(const SharedObjectPointerTemplate<T>& first,
|
||||||
const SharedObjectPointerTemplate<T, Inc, Dec>& first, const SharedObjectPointerTemplate<X, Inc2, Dec2>& second) {
|
const SharedObjectPointerTemplate<X>& second) {
|
||||||
return first ? first->equals(second) : !second;
|
return first ? first->equals(second) : !second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,11 +161,6 @@ typedef QSet<SharedObjectPointer> SharedObjectSet;
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(SharedObjectSet)
|
Q_DECLARE_METATYPE(SharedObjectSet)
|
||||||
|
|
||||||
typedef SharedObjectPointerTemplate<SharedObject, &SharedObject::incrementSoftReferenceCount,
|
|
||||||
&SharedObject::decrementSoftReferenceCount> SoftSharedObjectPointer;
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(SoftSharedObjectPointer)
|
|
||||||
|
|
||||||
/// Allows editing shared object instances.
|
/// Allows editing shared object instances.
|
||||||
class SharedObjectEditor : public QWidget {
|
class SharedObjectEditor : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
#include <MetavoxelMessages.h>
|
||||||
|
|
||||||
#include "MetavoxelTests.h"
|
#include "MetavoxelTests.h"
|
||||||
|
|
||||||
REGISTER_META_OBJECT(TestSharedObjectA)
|
REGISTER_META_OBJECT(TestSharedObjectA)
|
||||||
|
@ -245,6 +247,9 @@ void Endpoint::sendDatagram(const QByteArray& datagram) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Endpoint::handleHighPriorityMessage(const QVariant& message) {
|
void Endpoint::handleHighPriorityMessage(const QVariant& message) {
|
||||||
|
if (message.userType() == ClearSharedObjectMessage::Type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_other->_highPriorityMessagesSent.isEmpty()) {
|
if (_other->_highPriorityMessagesSent.isEmpty()) {
|
||||||
throw QString("Received unsent/already sent high priority message.");
|
throw QString("Received unsent/already sent high priority message.");
|
||||||
}
|
}
|
||||||
|
@ -274,6 +279,10 @@ void Endpoint::readMessage(Bitstream& in) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Endpoint::handleReliableMessage(const QVariant& message) {
|
void Endpoint::handleReliableMessage(const QVariant& message) {
|
||||||
|
if (message.userType() == ClearSharedObjectMessage::Type ||
|
||||||
|
message.userType() == ClearMainChannelSharedObjectMessage::Type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_other->_reliableMessagesSent.isEmpty()) {
|
if (_other->_reliableMessagesSent.isEmpty()) {
|
||||||
throw QString("Received unsent/already sent reliable message.");
|
throw QString("Received unsent/already sent reliable message.");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue