From 8e7ead2ead37b13dec7db60ae5aea42894cf1370 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Mar 2015 16:05:31 -0700 Subject: [PATCH] fix locking issue in enter/leave entity scripts --- examples/entityScripts/portal.js | 9 +++++++-- .../entities-renderer/src/EntityTreeRenderer.cpp | 12 +++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/examples/entityScripts/portal.js b/examples/entityScripts/portal.js index 5dd7849c38..4e2ec6ddaf 100644 --- a/examples/entityScripts/portal.js +++ b/examples/entityScripts/portal.js @@ -9,15 +9,20 @@ this.preload = function(entityID) { teleport = SoundCache.getSound("http://s3.amazonaws.com/hifi-public/birarda/teleport.raw"); - + var properties = Entities.getEntityProperties(entityID); - portalDestination = properties.userData; animationURL = properties.modelURL; print("The portal destination is " + portalDestination); } this.enterEntity = function(entityID) { + + var properties = Entities.getEntityProperties(entityID); // in case the userData/portalURL has changed + portalDestination = properties.userData; + + print("enterEntity() .... The portal destination is " + portalDestination); + if (portalDestination.length > 0) { print("Teleporting to hifi://" + portalDestination); Window.location = "hifi://" + portalDestination; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index b005f67f5e..3faa06fc53 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -277,7 +277,6 @@ void EntityTreeRenderer::update() { void EntityTreeRenderer::checkEnterLeaveEntities() { if (_tree && !_shuttingDown) { - _tree->lockForWrite(); // so that our scripts can do edits if they want glm::vec3 avatarPosition = _viewState->getAvatarPosition(); if (avatarPosition != _lastAvatarPosition) { @@ -286,6 +285,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { QVector entitiesContainingAvatar; // find the entities near us + _tree->lockForRead(); // don't let someone else change our tree while we search static_cast(_tree)->findEntities(avatarPosition, radius, foundEntities); // create a list of entities that actually contain the avatar's position @@ -294,6 +294,11 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { entitiesContainingAvatar << entity->getEntityItemID(); } } + _tree->unlock(); + + // Note: at this point we don't need to worry about the tree being locked, because we only deal with + // EntityItemIDs from here. The loadEntityScript() method is robust against attempting to load scripts + // for entity IDs that no longer exist. // for all of our previous containing entities, if they are no longer containing then send them a leave event foreach(const EntityItemID& entityID, _currentEntitiesInside) { @@ -322,14 +327,12 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { _currentEntitiesInside = entitiesContainingAvatar; _lastAvatarPosition = avatarPosition; } - _tree->unlock(); } } void EntityTreeRenderer::leaveAllEntities() { if (_tree && !_shuttingDown) { - _tree->lockForWrite(); // so that our scripts can do edits if they want - + // for all of our previous containing entities, if they are no longer containing then send them a leave event foreach(const EntityItemID& entityID, _currentEntitiesInside) { emit leaveEntity(entityID); @@ -344,7 +347,6 @@ void EntityTreeRenderer::leaveAllEntities() { // make sure our "last avatar position" is something other than our current position, so that on our // first chance, we'll check for enter/leave entity events. _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE); - _tree->unlock(); } } void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) {