tighten up locking in actions

This commit is contained in:
Seth Alves 2015-10-14 11:43:03 -07:00
parent 9a9e5b962e
commit fa2bf2b2d9
4 changed files with 135 additions and 94 deletions

View file

@ -37,37 +37,41 @@ AvatarActionHold::~AvatarActionHold() {
}
void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
AvatarSharedPointer holdingAvatarData = avatarManager->getAvatarBySessionID(_holderID);
std::shared_ptr<Avatar> holdingAvatar = std::static_pointer_cast<Avatar>(holdingAvatarData);
bool gotLock = false;
glm::quat rotation;
glm::vec3 position;
std::shared_ptr<Avatar> holdingAvatar = nullptr;
gotLock = withTryReadLock([&]{
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
AvatarSharedPointer holdingAvatarData = avatarManager->getAvatarBySessionID(_holderID);
holdingAvatar = std::static_pointer_cast<Avatar>(holdingAvatarData);
if (holdingAvatar) {
glm::vec3 offset;
glm::vec3 palmPosition;
glm::quat palmRotation;
if (_hand == "right") {
palmPosition = holdingAvatar->getRightPalmPosition();
palmRotation = holdingAvatar->getRightPalmRotation();
} else {
palmPosition = holdingAvatar->getLeftPalmPosition();
palmRotation = holdingAvatar->getLeftPalmRotation();
}
rotation = palmRotation * _relativeRotation;
offset = rotation * _relativePosition;
position = palmPosition + offset;
}
});
if (holdingAvatar) {
glm::quat rotation;
glm::vec3 position;
glm::vec3 offset;
bool gotLock = withTryReadLock([&]{
glm::vec3 palmPosition;
glm::quat palmRotation;
if (_hand == "right") {
palmPosition = holdingAvatar->getRightPalmPosition();
palmRotation = holdingAvatar->getRightPalmRotation();
} else {
palmPosition = holdingAvatar->getLeftPalmPosition();
palmRotation = holdingAvatar->getLeftPalmRotation();
}
rotation = palmRotation * _relativeRotation;
offset = rotation * _relativePosition;
position = palmPosition + offset;
});
if (gotLock) {
gotLock = withTryWriteLock([&]{
_positionalTarget = position;
_rotationalTarget = rotation;
});
_positionalTarget = position;
_rotationalTarget = rotation;
});
}
if (gotLock) {
ObjectActionSpring::updateActionWorker(deltaTimeStep);
}
@ -76,46 +80,61 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
bool AvatarActionHold::updateArguments(QVariantMap arguments) {
if (!ObjectAction::updateArguments(arguments)) {
return false;
}
bool ok = true;
glm::vec3 relativePosition =
EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false);
if (!ok) {
relativePosition = _relativePosition;
}
glm::vec3 relativePosition;
glm::quat relativeRotation;
float timeScale;
QString hand;
QUuid holderID;
bool needUpdate = false;
bool updateArgumentsSuceeded = true;
ok = true;
glm::quat relativeRotation =
EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false);
if (!ok) {
relativeRotation = _relativeRotation;
}
withReadLock([&]{
if (!ObjectAction::updateArguments(arguments)) {
updateArgumentsSuceeded = false;
return;
}
bool ok = true;
relativePosition = EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false);
if (!ok) {
relativePosition = _relativePosition;
}
ok = true;
float timeScale =
EntityActionInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false);
if (!ok) {
timeScale = _linearTimeScale;
}
ok = true;
relativeRotation = EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false);
if (!ok) {
relativeRotation = _relativeRotation;
}
ok = true;
QString hand =
EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false);
if (!ok || !(hand == "left" || hand == "right")) {
hand = _hand;
}
ok = true;
timeScale = EntityActionInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false);
if (!ok) {
timeScale = _linearTimeScale;
}
ok = true;
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto holderID = myAvatar->getSessionUUID();
ok = true;
hand = EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false);
if (!ok || !(hand == "left" || hand == "right")) {
hand = _hand;
}
if (relativePosition != _relativePosition
ok = true;
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
holderID = myAvatar->getSessionUUID();
if (relativePosition != _relativePosition
|| relativeRotation != _relativeRotation
|| timeScale != _linearTimeScale
|| hand != _hand
|| holderID != _holderID) {
needUpdate = true;
}
});
if (!updateArgumentsSuceeded) {
return false;
}
if (needUpdate) {
withWriteLock([&] {
_relativePosition = relativePosition;
_relativeRotation = relativeRotation;
@ -154,18 +173,20 @@ QByteArray AvatarActionHold::serialize() const {
QByteArray serializedActionArguments;
QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly);
dataStream << ACTION_TYPE_HOLD;
dataStream << getID();
dataStream << AvatarActionHold::holdVersion;
withReadLock([&]{
dataStream << ACTION_TYPE_HOLD;
dataStream << getID();
dataStream << AvatarActionHold::holdVersion;
dataStream << _holderID;
dataStream << _relativePosition;
dataStream << _relativeRotation;
dataStream << _linearTimeScale;
dataStream << _hand;
dataStream << _holderID;
dataStream << _relativePosition;
dataStream << _relativeRotation;
dataStream << _linearTimeScale;
dataStream << _hand;
dataStream << _expires;
dataStream << _tag;
dataStream << _expires;
dataStream << _tag;
});
return serializedActionArguments;
}
@ -187,15 +208,21 @@ void AvatarActionHold::deserialize(QByteArray serializedArguments) {
return;
}
dataStream >> _holderID;
dataStream >> _relativePosition;
dataStream >> _relativeRotation;
dataStream >> _linearTimeScale;
_angularTimeScale = _linearTimeScale;
dataStream >> _hand;
withWriteLock([&]{
dataStream >> _holderID;
dataStream >> _relativePosition;
dataStream >> _relativeRotation;
dataStream >> _linearTimeScale;
_angularTimeScale = _linearTimeScale;
dataStream >> _hand;
dataStream >> _expires;
dataStream >> _tag;
dataStream >> _expires;
dataStream >> _tag;
_active = true;
qDebug() << "deserialize hold: " << _holderID
<< _relativePosition.x << _relativePosition.y << _relativePosition.z
<< _hand;
_active = true;
});
}

View file

@ -53,16 +53,6 @@ public:
virtual bool shouldSuppressLocationEdits() { return false; }
protected:
virtual glm::vec3 getPosition() = 0;
virtual void setPosition(glm::vec3 position) = 0;
virtual glm::quat getRotation() = 0;
virtual void setRotation(glm::quat rotation) = 0;
virtual glm::vec3 getLinearVelocity() = 0;
virtual void setLinearVelocity(glm::vec3 linearVelocity) = 0;
virtual glm::vec3 getAngularVelocity() = 0;
virtual void setAngularVelocity(glm::vec3 angularVelocity) = 0;
// these look in the arguments map for a named argument. if it's not found or isn't well formed,
// ok will be set to false (note that it's never set to true -- set it to true before calling these).
// if required is true, failure to extract an argument will cause a warning to be printed.
@ -77,6 +67,16 @@ protected:
static QString extractStringArgument(QString objectName, QVariantMap arguments,
QString argumentName, bool& ok, bool required = true);
protected:
virtual glm::vec3 getPosition() = 0;
virtual void setPosition(glm::vec3 position) = 0;
virtual glm::quat getRotation() = 0;
virtual void setRotation(glm::quat rotation) = 0;
virtual glm::vec3 getLinearVelocity() = 0;
virtual void setLinearVelocity(glm::vec3 linearVelocity) = 0;
virtual glm::vec3 getAngularVelocity() = 0;
virtual void setAngularVelocity(glm::vec3 angularVelocity) = 0;
QUuid _id;
EntityActionType _type;
};

View file

@ -1630,8 +1630,6 @@ void EntityItem::deserializeActionsInternal() {
return;
}
// Keep track of which actions got added or updated by the new actionData
EntityTreePointer entityTree = _element ? _element->getTree() : nullptr;
assert(entityTree);
EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr;
@ -1643,6 +1641,7 @@ void EntityItem::deserializeActionsInternal() {
serializedActionsStream >> serializedActions;
}
// Keep track of which actions got added or updated by the new actionData
QSet<QUuid> updated;
foreach(QByteArray serializedAction, serializedActions) {
@ -1658,12 +1657,14 @@ void EntityItem::deserializeActionsInternal() {
updated << actionID;
if (_objectActions.contains(actionID)) {
qDebug() << "EntityItem::deserializeActionsInternal is UPDATING" << actionID;
EntityActionPointer action = _objectActions[actionID];
// TODO: make sure types match? there isn't currently a way to
// change the type of an existing action.
action->deserialize(serializedAction);
action->locallyAddedButNotYetReceived = false;
} else {
qDebug() << "EntityItem::deserializeActionsInternal is ADDING" << actionID;
auto actionFactory = DependencyManager::get<EntityActionFactoryInterface>();
EntityItemPointer entity = shared_from_this();
EntityActionPointer action = actionFactory->factoryBA(entity, serializedAction);

View file

@ -24,20 +24,33 @@ ObjectAction::~ObjectAction() {
}
void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
if (_ownerEntity.expired()) {
bool ownerEntityExpired = false;
quint64 expiresWhen = 0;
withReadLock([&]{
ownerEntityExpired = _ownerEntity.expired();
expiresWhen = _expires;
});
if (ownerEntityExpired) {
qDebug() << "warning -- action with no entity removing self from btCollisionWorld.";
btDynamicsWorld* dynamicsWorld = static_cast<btDynamicsWorld*>(collisionWorld);
dynamicsWorld->removeAction(this);
return;
}
if (_expires > 0) {
if (expiresWhen > 0) {
quint64 now = usecTimestampNow();
if (now > _expires) {
EntityItemPointer ownerEntity = _ownerEntity.lock();
_active = false;
if (now > expiresWhen) {
EntityItemPointer ownerEntity = nullptr;
QUuid myID;
withWriteLock([&]{
ownerEntity = _ownerEntity.lock();
_active = false;
myID = getID();
});
if (ownerEntity) {
ownerEntity->removeAction(nullptr, getID());
ownerEntity->removeAction(nullptr, myID);
}
}
}