History

abstract DiffTraversal out of EntityTreeSendThread

Andrew Meadows committed 9 years ago

Commit 0758b601 parent 5fba4cb6 files · +366 −276Browse files

Showing the changes to assignment-client/src/entities/EntityTreeSendThread.cpp (1 of 6 files). Show all

Unified · Split

assignment-client/src/entities/EntityTreeSendThread.cpp+42−131
@@ -10,19 +10,12 @@ · 9 unmodified lines
1010 //
1111
1212 #include "EntityTreeSendThread.h"
13−#include <iostream> // adebug
1413
1514 #include <EntityNodeData.h>
1615 #include <EntityTypes.h>
1716
1817 #include "EntityServer.h"
1918
20−EntityTreeSendThread::EntityTreeSendThread(OctreeServer* myServer, const SharedNodePointer& node)
21− : OctreeSendThread(myServer, node) {
22− const int32_t MIN_PATH_DEPTH = 16;
23− _traversalPath.reserve(MIN_PATH_DEPTH);
24−}
25−
2619 void EntityTreeSendThread::preDistributionProcessing() {
2720 auto node = _node.toStrongRef();
2821 auto nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
@@ -90,14 +83,14 @@ void EntityTreeSendThread::preDistributionProcessing() { · 61 unmodified lines
9083 void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
9184 bool viewFrustumChanged, bool isFullScene) {
9285 // BEGIN EXPERIMENTAL DIFFERENTIAL TRAVERSAL
93− {
94− // DEBUG HACK: trigger traversal (Again) every so often
95− const uint64_t TRAVERSE_AGAIN_PERIOD = 2 * USECS_PER_SECOND;
96− if (!viewFrustumChanged && usecTimestampNow() > _startOfCompletedTraversal + TRAVERSE_AGAIN_PERIOD) {
97− viewFrustumChanged = true;
98− }
99− }
10086 if (nodeData->getUsesFrustum()) {
87+ {
88+ // DEBUG HACK: trigger traversal (Again) every so often
89+ const uint64_t TRAVERSE_AGAIN_PERIOD = 4 * USECS_PER_SECOND;
90+ if (!viewFrustumChanged && usecTimestampNow() > _traversal.getStartOfCompletedTraversal() + TRAVERSE_AGAIN_PERIOD) {
91+ viewFrustumChanged = true;
92+ }
93+ }
10194 if (viewFrustumChanged) {
10295 ViewFrustum viewFrustum;
10396 nodeData->copyCurrentViewFrustum(viewFrustum);
@@ -105,28 +98,14 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O · 1 unmodified line
10598 startNewTraversal(viewFrustum, root);
10699 }
107100 }
108− if (!_traversalPath.empty()) {
101+ if (!_traversal.finished()) {
109102 uint64_t startTime = usecTimestampNow();
110− uint64_t now = startTime;
111103
112− VisibleElement next;
113− getNextVisibleElement(next);
114− while (next.element) {
115− if (next.element->hasContent()) {
116− _scanNextElementCallback(next);
117− }
104+ const uint64_t TIME_BUDGET = 100000; // usec
105+ _traversal.traverse(TIME_BUDGET);
118106
119− // TODO: pick a reasonable budget for each partial traversal
120− const uint64_t PARTIAL_TRAVERSAL_TIME_BUDGET = 100000; // usec
121− now = usecTimestampNow();
122− if (now - startTime > PARTIAL_TRAVERSAL_TIME_BUDGET) {
123− break;
124− }
125− getNextVisibleElement(next);
126− }
127−
128− uint64_t dt = now - startTime;
129− std::cout << "adebug traversal complete " << " Q.size = " << _sendQueue.size() << " dt = " << dt << std::endl; // adebug
107+ uint64_t dt = usecTimestampNow() - startTime;
108+ std::cout << "adebug traversal complete " << " Q.size = " << _sendQueue.size() << " dt = " << dt << std::endl; // adebug
130109 }
131110 if (!_sendQueue.empty()) {
132111 // print what needs to be sent
@@ -134,11 +113,9 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O · 1 unmodified line
134113 PrioritizedEntity entry = _sendQueue.top();
135114 EntityItemPointer entity = entry.getEntity();
136115 if (entity) {
137− std::cout << "adebug '" << entity->getName().toStdString() << "'"
138− << " : " << entry.getPriority() << std::endl; // adebug
116+ std::cout << "adebug send '" << entity->getName().toStdString() << "'" << " : " << entry.getPriority() << std::endl; // adebug
139117 }
140118 _sendQueue.pop();
141− std::cout << "adebug" << std::endl; // adebug
142119 }
143120 }
144121 // END EXPERIMENTAL DIFFERENTIAL TRAVERSAL
@@ -195,39 +172,29 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil · 50 unmodified lines
195172 return hasNewChild || hasNewDescendants;
196173 }
197174
198−void EntityTreeSendThread::startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root) {
175+void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root) {
176+ DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root);
199177 // there are three types of traversal:
200178 //
201179 // (1) FirstTime = at login --> find everything in view
202− // (2) Again = view hasn't changed --> find what has changed since last complete traversal
180+ // (2) Repeat = view hasn't changed --> find what has changed since last complete traversal
203181 // (3) Differential = view has changed --> find what has changed or in new view but not old
204182 //
205− // For each traversal type we define two callback lambdas:
206− //
207− // _getNextVisibleElementCallback = identifies elements that need to be traversed,i
208− // updates VisibleElement ref argument with pointer-to-element and view-intersection
209− // (INSIDE, INTERSECT, or OUTSIDE)
210− //
211− // _scanNextElementCallback = identifies entities that need to be appended to _sendQueue
183+ // The "scanCallback" we provide to the traversal depends on the type:
212184 //
213185 // The _conicalView is updated here as a cached view approximation used by the lambdas for efficient
214186 // computation of entity sorting priorities.
215187 //
216− if (_startOfCompletedTraversal == 0) {
217− // first time
218− _currentView = viewFrustum;
219− _conicalView.set(_currentView);
220−
221− _getNextVisibleElementCallback = [&](VisibleElement& next) {
222− _traversalPath.back().getNextVisibleElementFirstTime(next, _currentView);
223− };
188+ _conicalView.set(_traversal.getCurrentView());
224189
225− _scanNextElementCallback = [&](VisibleElement& next) {
190+ switch (type) {
191+ case DiffTraversal::First:
192+ _traversal.setScanCallback([&] (DiffTraversal::VisibleElement& next) {
226193 next.element->forEachEntity([&](EntityItemPointer entity) {
227194 bool success = false;
228195 AACube cube = entity->getQueryAACube(success);
229196 if (success) {
230− if (_currentView.cubeIntersectsKeyhole(cube)) {
197+ if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
231198 float priority = _conicalView.computePriority(cube);
232199 _sendQueue.push(PrioritizedEntity(entity, priority));
233200 }
@@ -236,21 +203,18 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& viewFrustum, Ent · 2 unmodified lines
236203 _sendQueue.push(PrioritizedEntity(entity, WHEN_IN_DOUBT_PRIORITY));
237204 }
238205 });
239− };
240− } else if (_currentView.isVerySimilar(viewFrustum)) {
241− // again
242− _getNextVisibleElementCallback = [&](VisibleElement& next) {
243− _traversalPath.back().getNextVisibleElementAgain(next, _currentView, _startOfCompletedTraversal);
244− };
245−
246− _scanNextElementCallback = [&](VisibleElement& next) {
247− if (next.element->getLastChangedContent() > _startOfCompletedTraversal) {
206+ });
207+ break;
208+ case DiffTraversal::Repeat:
209+ _traversal.setScanCallback([&] (DiffTraversal::VisibleElement& next) {
210+ if (next.element->getLastChangedContent() > _traversal.getStartOfCompletedTraversal()) {
211+ uint64_t timestamp = _traversal.getStartOfCompletedTraversal();
248212 next.element->forEachEntity([&](EntityItemPointer entity) {
249− if (entity->getLastEdited() > _startOfCompletedTraversal) {
213+ if (entity->getLastEdited() > timestamp) {
250214 bool success = false;
251215 AACube cube = entity->getQueryAACube(success);
252216 if (success) {
253− if (next.intersection == ViewFrustum::INSIDE || _currentView.cubeIntersectsKeyhole(cube)) {
217+ if (next.intersection == ViewFrustum::INSIDE || _traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
254218 float priority = _conicalView.computePriority(cube);
255219 _sendQueue.push(PrioritizedEntity(entity, priority));
256220 }
@@ -261,26 +225,20 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& viewFrustum, Ent · 4 unmodified lines
261225 }
262226 });
263227 }
264− };
265− } else {
266− // differential
267− _currentView = viewFrustum;
268− _conicalView.set(_currentView);
269−
270− _getNextVisibleElementCallback = [&](VisibleElement& next) {
271− _traversalPath.back().getNextVisibleElementDifferential(next, _currentView, _completedView, _startOfCompletedTraversal);
272− };
273−
274− _scanNextElementCallback = [&](VisibleElement& next) {
275− // NOTE: for differential case next.intersection is against _completedView not _currentView
276− if (next.element->getLastChangedContent() > _startOfCompletedTraversal || next.intersection != ViewFrustum::INSIDE) {
228+ });
229+ break;
230+ case DiffTraversal::Differential:
231+ _traversal.setScanCallback([&] (DiffTraversal::VisibleElement& next) {
232+ // NOTE: for Differential case: next.intersection is against completedView not currentView
233+ uint64_t timestamp = _traversal.getStartOfCompletedTraversal();
234+ if (next.element->getLastChangedContent() > timestamp || next.intersection != ViewFrustum::INSIDE) {
277235 next.element->forEachEntity([&](EntityItemPointer entity) {
278236 bool success = false;
279237 AACube cube = entity->getQueryAACube(success);
280238 if (success) {
281− if (_currentView.cubeIntersectsKeyhole(cube) &&
282− (entity->getLastEdited() > _startOfCompletedTraversal ||
283− !_completedView.cubeIntersectsKeyhole(cube))) {
239+ if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube) &&
240+ (entity->getLastEdited() > timestamp ||
241+ !_traversal.getCompletedView().cubeIntersectsKeyhole(cube))) {
284242 float priority = _conicalView.computePriority(cube);
285243 _sendQueue.push(PrioritizedEntity(entity, priority));
286244 }
@@ -290,55 +248,8 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& viewFrustum, Ent · 3 unmodified lines
290248 }
291249 });
292250 }
293− };
294− }
295−
296− _traversalPath.clear();
297− assert(root);
298− _traversalPath.push_back(TraversalWaypoint(root));
299− // set root fork's index such that root element returned at getNextElement()
300− _traversalPath.back().initRootNextIndex();
301−
302− _startOfCurrentTraversal = usecTimestampNow();
303−}
304−
305−void EntityTreeSendThread::getNextVisibleElement(VisibleElement& next) {
306− if (_traversalPath.empty()) {
307− next.element.reset();
308− next.intersection = ViewFrustum::OUTSIDE;
309− return;
310− }
311− _getNextVisibleElementCallback(next);
312− if (next.element) {
313− int8_t nextIndex = _traversalPath.back().getNextIndex();
314− if (nextIndex > 0) {
315− // next.element needs to be added to the path
316− _traversalPath.push_back(TraversalWaypoint(next.element));
317− }
318− } else {
319− // we're done at this level
320− while (!next.element) {
321− // pop one level
322− _traversalPath.pop_back();
323− if (_traversalPath.empty()) {
324− // we've traversed the entire tree
325− _completedView = _currentView;
326− _startOfCompletedTraversal = _startOfCurrentTraversal;
327− return;
328− }
329− // keep looking for next
330− _getNextVisibleElementCallback(next);
331− if (next.element) {
332− // we've descended one level so add it to the path
333− _traversalPath.push_back(TraversalWaypoint(next.element));
334− }
335− }
251+ });
252+ break;
336253 }
337254 }
338255
339−// DEBUG method: delete later
340−void EntityTreeSendThread::dump() const {
341− for (size_t i = 0; i < _traversalPath.size(); ++i) {
342− std::cout << (int32_t)(_traversalPath[i].getNextIndex()) << "-->";
343− }
344−}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t