From b31837168d15d4e5090b41ff03eef443ca34c97f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Sep 2018 11:27:20 -0700 Subject: [PATCH] fix bad lock, optimize some operations, clarify comment --- interface/src/avatar/AvatarManager.cpp | 4 +++- interface/src/avatar/AvatarManager.h | 4 +++- libraries/avatars/src/AvatarHashMap.cpp | 2 +- libraries/avatars/src/AvatarHashMap.h | 3 +-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d92a5c81da..0fdd246d7b 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -464,6 +464,8 @@ void AvatarManager::clearOtherAvatars() { { QWriteLocker locker(&_hashLock); + removedAvatars.reserve(_avatarHash.size()); + auto avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { auto avatar = std::static_pointer_cast(avatarIterator.value()); @@ -484,7 +486,7 @@ void AvatarManager::clearOtherAvatars() { void AvatarManager::deleteAllAvatars() { assert(_avatarsToChangeInPhysics.empty()); - QReadLocker locker(&_hashLock); + QWriteLocker locker(&_hashLock); AvatarHash::iterator avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { auto avatar = std::static_pointer_cast(avatarIterator.value()); diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 407b3c50de..9c4287728d 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -205,7 +205,9 @@ private: AvatarSharedPointer newSharedAvatar() override; - // must not be called while holding the hash lock + // called only from the AvatarHashMap thread - cannot be called while this thread holds the + // hash lock, since handleRemovedAvatar needs a write lock on the entity tree and the entity tree + // frequently grabs a read lock on the hash to get a given avatar by ID void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override; diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 2ee51cca17..01557e307e 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -73,7 +73,7 @@ std::vector AvatarReplicas::takeReplicas(const QUuid& paren if (it != _replicasMap.end()) { // take a copy of the replica shared pointers for this parent - replicas = it->second; + replicas.swap(it->second); // erase the replicas for this parent from our map _replicasMap.erase(it); diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 724dd1deac..c2cb448e52 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -180,8 +180,7 @@ protected: bool& isNew); virtual AvatarSharedPointer findAvatar(const QUuid& sessionUUID) const; // uses a QReadLocker on the hashLock virtual void removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason = KillAvatarReason::NoReason); - - // must not be called while holding the hash lock + virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason); AvatarHash _avatarHash;