Thread-safe avatar list access

This commit is contained in:
Howard Stearns 2015-10-22 13:02:08 -07:00
parent 27c6624f0c
commit 0d514ad645
3 changed files with 13 additions and 1 deletions

View file

@ -77,7 +77,10 @@ AvatarManager::AvatarManager(QObject* parent) :
void AvatarManager::init() { void AvatarManager::init() {
_myAvatar->init(); _myAvatar->init();
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar); {
QWriteLocker locker(&_hashLock);
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
}
connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged, this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection); connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged, this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
@ -127,6 +130,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
} else if (avatar->shouldDie()) { } else if (avatar->shouldDie()) {
removeAvatarMotionState(avatar); removeAvatarMotionState(avatar);
_avatarFades.push_back(avatarIterator.value()); _avatarFades.push_back(avatarIterator.value());
QWriteLocker locker(&_hashLock);
avatarIterator = _avatarHash.erase(avatarIterator); avatarIterator = _avatarHash.erase(avatarIterator);
} else { } else {
avatar->startUpdate(); avatar->startUpdate();
@ -202,6 +206,7 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
if (avatar != _myAvatar && avatar->isInitialized()) { if (avatar != _myAvatar && avatar->isInitialized()) {
removeAvatarMotionState(avatar); removeAvatarMotionState(avatar);
_avatarFades.push_back(avatarIterator.value()); _avatarFades.push_back(avatarIterator.value());
QWriteLocker locker(&_hashLock);
_avatarHash.erase(avatarIterator); _avatarHash.erase(avatarIterator);
} }
} }
@ -218,6 +223,7 @@ void AvatarManager::clearOtherAvatars() {
} else { } else {
removeAvatarMotionState(avatar); removeAvatarMotionState(avatar);
_avatarFades.push_back(avatarIterator.value()); _avatarFades.push_back(avatarIterator.value());
QWriteLocker locker(&_hashLock);
avatarIterator = _avatarHash.erase(avatarIterator); avatarIterator = _avatarHash.erase(avatarIterator);
} }
} }

View file

@ -23,6 +23,7 @@ AvatarHashMap::AvatarHashMap() {
} }
bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) { bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) {
QReadLocker locker(&_hashLock);
foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) { foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) {
glm::vec3 avatarPosition = sharedAvatar->getPosition(); glm::vec3 avatarPosition = sharedAvatar->getPosition();
float distance = glm::distance(avatarPosition, position); float distance = glm::distance(avatarPosition, position);
@ -43,6 +44,7 @@ AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWe
AvatarSharedPointer avatar = newSharedAvatar(); AvatarSharedPointer avatar = newSharedAvatar();
avatar->setSessionUUID(sessionUUID); avatar->setSessionUUID(sessionUUID);
avatar->setOwningAvatarMixer(mixerWeakPointer); avatar->setOwningAvatarMixer(mixerWeakPointer);
QWriteLocker locker(&_hashLock);
_avatarHash.insert(sessionUUID, avatar); _avatarHash.insert(sessionUUID, avatar);
return avatar; return avatar;
@ -134,6 +136,7 @@ void AvatarHashMap::processKillAvatar(QSharedPointer<NLPacket> packet, SharedNod
} }
void AvatarHashMap::removeAvatar(const QUuid& sessionUUID) { void AvatarHashMap::removeAvatar(const QUuid& sessionUUID) {
QWriteLocker locker(&_hashLock);
_avatarHash.remove(sessionUUID); _avatarHash.remove(sessionUUID);
} }

View file

@ -52,6 +52,9 @@ protected:
virtual void removeAvatar(const QUuid& sessionUUID); virtual void removeAvatar(const QUuid& sessionUUID);
AvatarHash _avatarHash; AvatarHash _avatarHash;
// "Case-based safety": Most access to the _avatarHash is on the same thread. Write access is protected by a write lock.
// If you access from a different thread, it is your responsibility to write- or read-lock the _hashLock.
QReadWriteLock _hashLock;
private: private:
QUuid _lastOwnerSessionUUID; QUuid _lastOwnerSessionUUID;