mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 10:29:01 +02:00
Fix entity server crash
This commit is contained in:
parent
7a710093ac
commit
69a7f2d4aa
3 changed files with 54 additions and 16 deletions
|
@ -13,6 +13,7 @@
|
||||||
#define hifi_EntityPriorityQueue_h
|
#define hifi_EntityPriorityQueue_h
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <AACube.h>
|
#include <AACube.h>
|
||||||
#include <DiffTraversal.h>
|
#include <DiffTraversal.h>
|
||||||
|
@ -71,6 +72,50 @@ private:
|
||||||
bool _forceRemove;
|
bool _forceRemove;
|
||||||
};
|
};
|
||||||
|
|
||||||
using EntityPriorityQueue = std::priority_queue< PrioritizedEntity, std::vector<PrioritizedEntity>, PrioritizedEntity::Compare >;
|
class EntityPriorityQueue {
|
||||||
|
public:
|
||||||
|
inline bool empty() const {
|
||||||
|
assert(_queue.empty() == _entities.empty());
|
||||||
|
return _queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const PrioritizedEntity& top() const {
|
||||||
|
assert(!_queue.empty());
|
||||||
|
return _queue.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool contains(const EntityItem* entity) const {
|
||||||
|
return _entities.find(entity) != std::end(_entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void emplace(const EntityItemPointer& entity, float priority, bool forceRemove = false) {
|
||||||
|
assert(entity && !contains(entity.get()));
|
||||||
|
_queue.emplace(entity, priority, forceRemove);
|
||||||
|
_entities.insert(entity.get());
|
||||||
|
assert(_queue.size() == _entities.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void pop() {
|
||||||
|
assert(!empty());
|
||||||
|
_entities.erase(_queue.top().getRawEntityPointer());
|
||||||
|
_queue.pop();
|
||||||
|
assert(_queue.size() == _entities.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void swap(EntityPriorityQueue& other) {
|
||||||
|
std::swap(_queue, other._queue);
|
||||||
|
std::swap(_entities, other._entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
using PriorityQueue = std::priority_queue<PrioritizedEntity,
|
||||||
|
std::vector<PrioritizedEntity>,
|
||||||
|
PrioritizedEntity::Compare>;
|
||||||
|
|
||||||
|
PriorityQueue _queue;
|
||||||
|
// Keep dictionary of al the entities in the queue for fast contain checks.
|
||||||
|
std::unordered_set<const EntityItem*> _entities;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityPriorityQueue_h
|
#endif // hifi_EntityPriorityQueue_h
|
||||||
|
|
|
@ -127,8 +127,9 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
|
||||||
// and also use the opportunity to cull anything no longer in view
|
// and also use the opportunity to cull anything no longer in view
|
||||||
if (viewFrustumChanged && !_sendQueue.empty()) {
|
if (viewFrustumChanged && !_sendQueue.empty()) {
|
||||||
EntityPriorityQueue prevSendQueue;
|
EntityPriorityQueue prevSendQueue;
|
||||||
_sendQueue.swap(prevSendQueue);
|
std::swap(_sendQueue, prevSendQueue);
|
||||||
_entitiesInQueue.clear();
|
assert(_sendQueue.empty());
|
||||||
|
|
||||||
// Re-add elements from previous traversal if they still need to be sent
|
// Re-add elements from previous traversal if they still need to be sent
|
||||||
while (!prevSendQueue.empty()) {
|
while (!prevSendQueue.empty()) {
|
||||||
EntityItemPointer entity = prevSendQueue.top().getEntity();
|
EntityItemPointer entity = prevSendQueue.top().getEntity();
|
||||||
|
@ -156,7 +157,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
|
||||||
|
|
||||||
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
||||||
_sendQueue.emplace(entity, priority, forceRemove);
|
_sendQueue.emplace(entity, priority, forceRemove);
|
||||||
_entitiesInQueue.insert(entity.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
|
||||||
_traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
|
_traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) {
|
||||||
next.element->forEachEntity([&](EntityItemPointer entity) {
|
next.element->forEachEntity([&](EntityItemPointer entity) {
|
||||||
// Bail early if we've already checked this entity this frame
|
// Bail early if we've already checked this entity this frame
|
||||||
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
|
if (_sendQueue.contains(entity.get())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float priority = PrioritizedEntity::DO_NOT_SEND;
|
float priority = PrioritizedEntity::DO_NOT_SEND;
|
||||||
|
@ -275,7 +275,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
|
||||||
|
|
||||||
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
||||||
_sendQueue.emplace(entity, priority);
|
_sendQueue.emplace(entity, priority);
|
||||||
_entitiesInQueue.insert(entity.get());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -286,7 +285,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
|
||||||
if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
|
if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
|
||||||
next.element->forEachEntity([&](EntityItemPointer entity) {
|
next.element->forEachEntity([&](EntityItemPointer entity) {
|
||||||
// Bail early if we've already checked this entity this frame
|
// Bail early if we've already checked this entity this frame
|
||||||
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
|
if (_sendQueue.contains(entity.get())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float priority = PrioritizedEntity::DO_NOT_SEND;
|
float priority = PrioritizedEntity::DO_NOT_SEND;
|
||||||
|
@ -315,7 +314,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
|
||||||
|
|
||||||
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
||||||
_sendQueue.emplace(entity, priority);
|
_sendQueue.emplace(entity, priority);
|
||||||
_entitiesInQueue.insert(entity.get());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -326,7 +324,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
|
||||||
_traversal.setScanCallback([this] (DiffTraversal::VisibleElement& next) {
|
_traversal.setScanCallback([this] (DiffTraversal::VisibleElement& next) {
|
||||||
next.element->forEachEntity([&](EntityItemPointer entity) {
|
next.element->forEachEntity([&](EntityItemPointer entity) {
|
||||||
// Bail early if we've already checked this entity this frame
|
// Bail early if we've already checked this entity this frame
|
||||||
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
|
if (_sendQueue.contains(entity.get())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float priority = PrioritizedEntity::DO_NOT_SEND;
|
float priority = PrioritizedEntity::DO_NOT_SEND;
|
||||||
|
@ -358,7 +356,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En
|
||||||
|
|
||||||
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
||||||
_sendQueue.emplace(entity, priority);
|
_sendQueue.emplace(entity, priority);
|
||||||
_entitiesInQueue.insert(entity.get());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -447,11 +444,10 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_sendQueue.pop();
|
_sendQueue.pop();
|
||||||
_entitiesInQueue.erase(entity.get());
|
|
||||||
}
|
}
|
||||||
nodeData->stats.encodeStopped();
|
nodeData->stats.encodeStopped();
|
||||||
if (_sendQueue.empty()) {
|
if (_sendQueue.empty()) {
|
||||||
assert(_entitiesInQueue.empty());
|
assert(_sendQueue.empty());
|
||||||
params.stopReason = EncodeBitstreamParams::FINISHED;
|
params.stopReason = EncodeBitstreamParams::FINISHED;
|
||||||
_extraEncodeData->entities.clear();
|
_extraEncodeData->entities.clear();
|
||||||
}
|
}
|
||||||
|
@ -469,18 +465,16 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
|
||||||
|
|
||||||
void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity) {
|
void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity) {
|
||||||
if (entity) {
|
if (entity) {
|
||||||
if (_entitiesInQueue.find(entity.get()) == _entitiesInQueue.end() && _knownState.find(entity.get()) != _knownState.end()) {
|
if (!_sendQueue.contains(entity.get()) && _knownState.find(entity.get()) != _knownState.end()) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
AACube cube = entity->getQueryAACube(success);
|
AACube cube = entity->getQueryAACube(success);
|
||||||
if (success) {
|
if (success) {
|
||||||
// We can force a removal from _knownState if the current view is used and entity is out of view
|
// We can force a removal from _knownState if the current view is used and entity is out of view
|
||||||
if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) {
|
if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) {
|
||||||
_sendQueue.emplace(entity, PrioritizedEntity::FORCE_REMOVE, true);
|
_sendQueue.emplace(entity, PrioritizedEntity::FORCE_REMOVE, true);
|
||||||
_entitiesInQueue.insert(entity.get());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_sendQueue.emplace(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true);
|
_sendQueue.emplace(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true);
|
||||||
_entitiesInQueue.insert(entity.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@ private:
|
||||||
|
|
||||||
DiffTraversal _traversal;
|
DiffTraversal _traversal;
|
||||||
EntityPriorityQueue _sendQueue;
|
EntityPriorityQueue _sendQueue;
|
||||||
std::unordered_set<EntityItem*> _entitiesInQueue;
|
|
||||||
std::unordered_map<EntityItem*, uint64_t> _knownState;
|
std::unordered_map<EntityItem*, uint64_t> _knownState;
|
||||||
ConicalView _conicalView; // cached optimized view for fast priority calculations
|
ConicalView _conicalView; // cached optimized view for fast priority calculations
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue