_avatarEntityData is accessed by more than one thread.

This commit is contained in:
Seth Alves 2016-06-08 15:53:54 -07:00
parent 4e418f328f
commit f070708b4a
4 changed files with 65 additions and 39 deletions

View file

@ -240,12 +240,14 @@ void Avatar::updateAvatarEntities() {
} }
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs(); AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
_avatarEntitiesLock.withReadLock([&] {
foreach (auto entityID, recentlyDettachedAvatarEntities) { foreach (auto entityID, recentlyDettachedAvatarEntities) {
if (!_avatarEntityData.contains(entityID)) { if (!_avatarEntityData.contains(entityID)) {
entityTree->deleteEntity(entityID, true, true); entityTree->deleteEntity(entityID, true, true);
} }
} }
}); });
});
if (success) { if (success) {
setAvatarEntityDataChanged(false); setAvatarEntityDataChanged(false);

View file

@ -723,12 +723,14 @@ void MyAvatar::saveData() {
settings.beginWriteArray("avatarEntityData"); settings.beginWriteArray("avatarEntityData");
int avatarEntityIndex = 0; int avatarEntityIndex = 0;
_avatarEntitiesLock.withReadLock([&] {
for (auto entityID : _avatarEntityData.keys()) { for (auto entityID : _avatarEntityData.keys()) {
settings.setArrayIndex(avatarEntityIndex); settings.setArrayIndex(avatarEntityIndex);
settings.setValue("id", entityID); settings.setValue("id", entityID);
settings.setValue("properties", _avatarEntityData.value(entityID)); settings.setValue("properties", _avatarEntityData.value(entityID));
avatarEntityIndex++; avatarEntityIndex++;
} }
});
settings.endArray(); settings.endArray();
settings.setValue("displayName", _displayName); settings.setValue("displayName", _displayName);

View file

@ -900,7 +900,11 @@ bool AvatarData::processAvatarIdentity(const Identity& identity) {
hasIdentityChanged = true; hasIdentityChanged = true;
} }
if (identity.avatarEntityData != _avatarEntityData) { bool avatarEntityDataChanged = false;
_avatarEntitiesLock.withReadLock([&] {
avatarEntityDataChanged = (identity.avatarEntityData != _avatarEntityData);
});
if (avatarEntityDataChanged) {
setAvatarEntityData(identity.avatarEntityData); setAvatarEntityData(identity.avatarEntityData);
hasIdentityChanged = true; hasIdentityChanged = true;
} }
@ -914,7 +918,9 @@ QByteArray AvatarData::identityByteArray() {
QUrl emptyURL(""); QUrl emptyURL("");
const QUrl& urlToSend = _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL; const QUrl& urlToSend = _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL;
_avatarEntitiesLock.withReadLock([&] {
identityStream << getSessionUUID() << urlToSend << _attachmentData << _displayName << _avatarEntityData; identityStream << getSessionUUID() << urlToSend << _attachmentData << _displayName << _avatarEntityData;
});
return identityData; return identityData;
} }
@ -1306,6 +1312,7 @@ QJsonObject AvatarData::toJson() const {
root[JSON_AVATAR_ATTACHEMENTS] = attachmentsJson; root[JSON_AVATAR_ATTACHEMENTS] = attachmentsJson;
} }
_avatarEntitiesLock.withReadLock([&] {
if (!_avatarEntityData.empty()) { if (!_avatarEntityData.empty()) {
QJsonArray avatarEntityJson; QJsonArray avatarEntityJson;
for (auto entityID : _avatarEntityData.keys()) { for (auto entityID : _avatarEntityData.keys()) {
@ -1316,6 +1323,7 @@ QJsonObject AvatarData::toJson() const {
} }
root[JSON_AVATAR_ENTITIES] = avatarEntityJson; root[JSON_AVATAR_ENTITIES] = avatarEntityJson;
} }
});
auto recordingBasis = getRecordingBasis(); auto recordingBasis = getRecordingBasis();
bool success; bool success;
@ -1604,8 +1612,10 @@ void AvatarData::updateAvatarEntity(const QUuid& entityID, const QByteArray& ent
QMetaObject::invokeMethod(this, "updateAvatarEntity", Q_ARG(const QUuid&, entityID), Q_ARG(QByteArray, entityData)); QMetaObject::invokeMethod(this, "updateAvatarEntity", Q_ARG(const QUuid&, entityID), Q_ARG(QByteArray, entityData));
return; return;
} }
_avatarEntitiesLock.withWriteLock([&] {
_avatarEntityData.insert(entityID, entityData); _avatarEntityData.insert(entityID, entityData);
_avatarEntityDataLocallyEdited = true; _avatarEntityDataLocallyEdited = true;
});
} }
void AvatarData::clearAvatarEntity(const QUuid& entityID) { void AvatarData::clearAvatarEntity(const QUuid& entityID) {
@ -1613,18 +1623,25 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID) {
QMetaObject::invokeMethod(this, "clearAvatarEntity", Q_ARG(const QUuid&, entityID)); QMetaObject::invokeMethod(this, "clearAvatarEntity", Q_ARG(const QUuid&, entityID));
return; return;
} }
_avatarEntitiesLock.withWriteLock([&] {
_avatarEntityData.remove(entityID); _avatarEntityData.remove(entityID);
_avatarEntityDataLocallyEdited = true; _avatarEntityDataLocallyEdited = true;
});
} }
AvatarEntityMap AvatarData::getAvatarEntityData() const { AvatarEntityMap AvatarData::getAvatarEntityData() const {
if (QThread::currentThread() != thread()) {
AvatarEntityMap result; AvatarEntityMap result;
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getAvatarEntityData", Qt::BlockingQueuedConnection, QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getAvatarEntityData", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(AvatarEntityMap, result)); Q_RETURN_ARG(AvatarEntityMap, result));
return result; return result;
} }
return _avatarEntityData;
_avatarEntitiesLock.withReadLock([&] {
result = _avatarEntityData;
});
return result;
} }
void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) { void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
@ -1632,6 +1649,7 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
QMetaObject::invokeMethod(this, "setAvatarEntityData", Q_ARG(const AvatarEntityMap&, avatarEntityData)); QMetaObject::invokeMethod(this, "setAvatarEntityData", Q_ARG(const AvatarEntityMap&, avatarEntityData));
return; return;
} }
_avatarEntitiesLock.withWriteLock([&] {
if (_avatarEntityData != avatarEntityData) { if (_avatarEntityData != avatarEntityData) {
// keep track of entities that were attached to this avatar but no longer are // keep track of entities that were attached to this avatar but no longer are
AvatarEntityIDs previousAvatarEntityIDs = QSet<QUuid>::fromList(_avatarEntityData.keys()); AvatarEntityIDs previousAvatarEntityIDs = QSet<QUuid>::fromList(_avatarEntityData.keys());
@ -1645,16 +1663,19 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
} }
} }
} }
});
} }
AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() { AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() {
if (QThread::currentThread() != thread()) {
AvatarEntityIDs result; AvatarEntityIDs result;
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getRecentlyDetachedIDs", Qt::BlockingQueuedConnection, QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getRecentlyDetachedIDs", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(AvatarEntityIDs, result)); Q_RETURN_ARG(AvatarEntityIDs, result));
return result; return result;
} }
AvatarEntityIDs result = _avatarEntityDetached; _avatarEntitiesLock.withWriteLock([&] {
result = _avatarEntityDetached;
_avatarEntityDetached.clear(); _avatarEntityDetached.clear();
});
return result; return result;
} }

View file

@ -418,6 +418,7 @@ protected:
// updates about one avatar to another. // updates about one avatar to another.
glm::vec3 _globalPosition; glm::vec3 _globalPosition;
mutable ReadWriteLockable _avatarEntitiesLock;
AvatarEntityIDs _avatarEntityDetached; // recently detached from this avatar AvatarEntityIDs _avatarEntityDetached; // recently detached from this avatar
AvatarEntityMap _avatarEntityData; AvatarEntityMap _avatarEntityData;
bool _avatarEntityDataLocallyEdited { false }; bool _avatarEntityDataLocallyEdited { false };