Merge pull request #14192 from Atlante45/fix/traits-race

Prevent race on internal client traits members
This commit is contained in:
Stephen Birarda 2018-10-23 14:53:11 -07:00 committed by GitHub
commit b789fa96f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 11 deletions

View file

@ -21,7 +21,6 @@
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <QUuid> #include <QUuid>
#include <ClientTraitsHandler.h>
#include <EntityEditPacketSender.h> #include <EntityEditPacketSender.h>
#include <EntityTree.h> #include <EntityTree.h>
#include <ScriptEngine.h> #include <ScriptEngine.h>

View file

@ -26,6 +26,7 @@
#include <AccountManager.h> #include <AccountManager.h>
#include <AddressManager.h> #include <AddressManager.h>
#include <AudioClient.h> #include <AudioClient.h>
#include <ClientTraitsHandler.h>
#include <display-plugins/DisplayPlugin.h> #include <display-plugins/DisplayPlugin.h>
#include <FSTReader.h> #include <FSTReader.h>
#include <GeometryUtil.h> #include <GeometryUtil.h>

View file

@ -21,7 +21,6 @@
#include <AvatarConstants.h> #include <AvatarConstants.h>
#include <avatars-renderer/Avatar.h> #include <avatars-renderer/Avatar.h>
#include <avatars-renderer/ScriptAvatar.h> #include <avatars-renderer/ScriptAvatar.h>
#include <ClientTraitsHandler.h>
#include <controllers/Pose.h> #include <controllers/Pose.h>
#include <controllers/Actions.h> #include <controllers/Actions.h>
#include <EntityItem.h> #include <EntityItem.h>

View file

@ -31,7 +31,27 @@ ClientTraitsHandler::ClientTraitsHandler(AvatarData* owningAvatar) :
nodeList->getPacketReceiver().registerListener(PacketType::SetAvatarTraits, this, "processTraitOverride"); nodeList->getPacketReceiver().registerListener(PacketType::SetAvatarTraits, this, "processTraitOverride");
} }
void ClientTraitsHandler::markTraitUpdated(AvatarTraits::TraitType updatedTrait) {
Lock lock(_traitLock);
_traitStatuses[updatedTrait] = Updated;
_hasChangedTraits = true;
}
void ClientTraitsHandler::markInstancedTraitUpdated(AvatarTraits::TraitType traitType, QUuid updatedInstanceID) {
Lock lock(_traitLock);
_traitStatuses.instanceInsert(traitType, updatedInstanceID, Updated);
_hasChangedTraits = true;
}
void ClientTraitsHandler::markInstancedTraitDeleted(AvatarTraits::TraitType traitType, QUuid deleteInstanceID) {
Lock lock(_traitLock);
_traitStatuses.instanceInsert(traitType, deleteInstanceID, Deleted);
_hasChangedTraits = true;
}
void ClientTraitsHandler::resetForNewMixer() { void ClientTraitsHandler::resetForNewMixer() {
Lock lock(_traitLock);
// re-set the current version to 0 // re-set the current version to 0
_currentTraitVersion = AvatarTraits::DEFAULT_TRAIT_VERSION; _currentTraitVersion = AvatarTraits::DEFAULT_TRAIT_VERSION;
@ -46,6 +66,8 @@ void ClientTraitsHandler::resetForNewMixer() {
} }
void ClientTraitsHandler::sendChangedTraitsToMixer() { void ClientTraitsHandler::sendChangedTraitsToMixer() {
Lock lock(_traitLock);
if (hasChangedTraits() || _shouldPerformInitialSend) { if (hasChangedTraits() || _shouldPerformInitialSend) {
// we have at least one changed trait to send // we have at least one changed trait to send
@ -113,6 +135,7 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() {
void ClientTraitsHandler::processTraitOverride(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) { void ClientTraitsHandler::processTraitOverride(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
if (sendingNode->getType() == NodeType::AvatarMixer) { if (sendingNode->getType() == NodeType::AvatarMixer) {
Lock lock(_traitLock);
while (message->getBytesLeftToRead()) { while (message->getBytesLeftToRead()) {
AvatarTraits::TraitType traitType; AvatarTraits::TraitType traitType;
message->readPrimitive(&traitType); message->readPrimitive(&traitType);

View file

@ -26,14 +26,11 @@ public:
void sendChangedTraitsToMixer(); void sendChangedTraitsToMixer();
bool hasChangedTraits() { return _hasChangedTraits; } bool hasChangedTraits() const { return _hasChangedTraits; }
void markTraitUpdated(AvatarTraits::TraitType updatedTrait) void markTraitUpdated(AvatarTraits::TraitType updatedTrait);
{ _traitStatuses[updatedTrait] = Updated; _hasChangedTraits = true; } void markInstancedTraitUpdated(AvatarTraits::TraitType traitType, QUuid updatedInstanceID);
void markInstancedTraitUpdated(AvatarTraits::TraitType traitType, QUuid updatedInstanceID) void markInstancedTraitDeleted(AvatarTraits::TraitType traitType, QUuid deleteInstanceID);
{ _traitStatuses.instanceInsert(traitType, updatedInstanceID, Updated); _hasChangedTraits = true; }
void markInstancedTraitDeleted(AvatarTraits::TraitType traitType, QUuid deleteInstanceID)
{ _traitStatuses.instanceInsert(traitType, deleteInstanceID, Deleted); _hasChangedTraits = true; }
void resetForNewMixer(); void resetForNewMixer();
@ -41,17 +38,21 @@ public slots:
void processTraitOverride(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode); void processTraitOverride(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
private: private:
using Mutex = std::recursive_mutex;
using Lock = std::lock_guard<Mutex>;
enum ClientTraitStatus { enum ClientTraitStatus {
Unchanged, Unchanged,
Updated, Updated,
Deleted Deleted
}; };
AvatarData* _owningAvatar; AvatarData* const _owningAvatar;
Mutex _traitLock;
AvatarTraits::AssociatedTraitValues<ClientTraitStatus, Unchanged> _traitStatuses; AvatarTraits::AssociatedTraitValues<ClientTraitStatus, Unchanged> _traitStatuses;
AvatarTraits::TraitVersion _currentTraitVersion { AvatarTraits::DEFAULT_TRAIT_VERSION };
AvatarTraits::TraitVersion _currentTraitVersion { AvatarTraits::DEFAULT_TRAIT_VERSION };
AvatarTraits::TraitVersion _currentSkeletonVersion { AvatarTraits::NULL_TRAIT_VERSION }; AvatarTraits::TraitVersion _currentSkeletonVersion { AvatarTraits::NULL_TRAIT_VERSION };
bool _shouldPerformInitialSend { false }; bool _shouldPerformInitialSend { false };