MirrorPropWebSocket: improve node recycling
Adjust logic for node recycling so common patterns observed with remote canvas work correctly (remove + add of same nodes).
This commit is contained in:
parent
d0017f3bec
commit
9723f26f23
1 changed files with 46 additions and 26 deletions
|
@ -35,6 +35,8 @@
|
||||||
|
|
||||||
#include <3rdparty/cjson/cJSON.h>
|
#include <3rdparty/cjson/cJSON.h>
|
||||||
|
|
||||||
|
//#define MIRROR_DEBUG 1
|
||||||
|
|
||||||
namespace flightgear {
|
namespace flightgear {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
|
@ -75,7 +77,7 @@ using std::string;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SG_LOG(SG_NETWORK, SG_INFO, "implement me!" << type);
|
SG_LOG(SG_NETWORK, SG_DEV_ALERT, "MirrorPropTree PropertyValue : implement me!" << type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,21 +117,22 @@ using std::string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct RecentlyRemovedNode
|
struct RemovedNode
|
||||||
{
|
{
|
||||||
RecentlyRemovedNode() { }
|
RemovedNode(SGPropertyNode* node, unsigned int aId) :
|
||||||
|
|
||||||
RecentlyRemovedNode(SGPropertyNode* node, unsigned int aId) :
|
|
||||||
type(node->getType()),
|
|
||||||
path(node->getPath()),
|
path(node->getPath()),
|
||||||
id(aId)
|
id(aId)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
simgear::props::Type type = simgear::props::NONE;
|
|
||||||
std::string path;
|
std::string path;
|
||||||
unsigned int id = 0;
|
unsigned int id = 0;
|
||||||
|
|
||||||
|
bool operator==(const RemovedNode& other) const
|
||||||
|
{
|
||||||
|
return (path == other.path);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MirrorTreeListener : public SGPropertyChangeListener
|
class MirrorTreeListener : public SGPropertyChangeListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -166,28 +169,40 @@ using std::string;
|
||||||
|
|
||||||
void recursiveAdd(SGPropertyNode* node)
|
void recursiveAdd(SGPropertyNode* node)
|
||||||
{
|
{
|
||||||
const auto type = node->getType();
|
RemovedNode r(node, 0 /* id not actually used */);
|
||||||
const auto& path = node->getPath();
|
#if defined (MIRROR_DEBUG)
|
||||||
auto rrIt = std::find_if(recentlyRemoved.begin(), recentlyRemoved.end(),
|
SG_LOG(SG_NETWORK, SG_INFO, "looking for RR:" << r.path);
|
||||||
[type, &path](const RecentlyRemovedNode& rr)
|
#endif
|
||||||
{ return (type == rr.type) && (path == rr.path); });
|
auto rrIt = std::find(recentlyRemoved.begin(), recentlyRemoved.end(), r);
|
||||||
if (rrIt != recentlyRemoved.end()) {
|
if (rrIt != recentlyRemoved.end()) {
|
||||||
|
#if defined (MIRROR_DEBUG)
|
||||||
|
SG_LOG(SG_NETWORK, SG_INFO, "recycling node:" << node->getPath());
|
||||||
|
#endif
|
||||||
|
const auto id = rrIt->id;
|
||||||
// recycle nodes which get thrashed from Nasal (deleted + re-created
|
// recycle nodes which get thrashed from Nasal (deleted + re-created
|
||||||
// each time a Nasal timer fires)
|
// each time a Nasal timer fires)
|
||||||
removedNodes.erase(rrIt->id); // don't remove it!
|
removedNodes.erase(id); // don't remove it!
|
||||||
idHash.insert(std::make_pair(node, rrIt->id));
|
idHash.insert(std::make_pair(node, id));
|
||||||
changedNodes.insert(node);
|
|
||||||
|
// we can still do change compression here, but this also
|
||||||
|
// deals with type mutation when removing + re-adding with a
|
||||||
|
// different type
|
||||||
|
PropertyValue newVal(node);
|
||||||
|
if (!previousValues[id].equals(node, newVal)) {
|
||||||
|
previousValues[id] = newVal;
|
||||||
|
changedNodes.insert(node);
|
||||||
|
#if defined (MIRROR_DEBUG)
|
||||||
|
SG_LOG(SG_NETWORK, SG_INFO, "\tand will actually change" << node->getPath());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
recentlyRemoved.erase(rrIt);
|
recentlyRemoved.erase(rrIt);
|
||||||
#if defined (MIRROR_DEBUG)
|
|
||||||
SG_LOG(SG_NETWORK, SG_INFO, "recycling node:" << path);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined (MIRROR_DEBUG)
|
#if defined (MIRROR_DEBUG)
|
||||||
SG_LOG(SG_NETWORK, SG_INFO, "new node:" << path);
|
SG_LOG(SG_NETWORK, SG_INFO, "new node:" << node->getPath());
|
||||||
#endif
|
#endif
|
||||||
newNodes.insert(node);
|
newNodes.insert(node);
|
||||||
|
|
||||||
int child = 0;
|
int child = 0;
|
||||||
for (; child < node->nChildren(); ++child) {
|
for (; child < node->nChildren(); ++child) {
|
||||||
recursiveAdd(node->getChild(child));
|
recursiveAdd(node->getChild(child));
|
||||||
|
@ -203,12 +218,17 @@ using std::string;
|
||||||
if (it != idHash.end()) {
|
if (it != idHash.end()) {
|
||||||
removedNodes.insert(it->second);
|
removedNodes.insert(it->second);
|
||||||
idHash.erase(it);
|
idHash.erase(it);
|
||||||
|
|
||||||
// record so we can map removed+add of the same property into
|
// record so we can map removed+add of the same property into
|
||||||
// a simple value change (this happens commonly with the canvas
|
// a simple value change (this happens commonly with the canvas
|
||||||
// due to lazy Nasal scripting)
|
// due to lazy Nasal scripting)
|
||||||
recentlyRemoved.emplace_back(child, it->second);
|
recentlyRemoved.emplace_back(child, it->second);
|
||||||
|
#if defined (MIRROR_DEBUG)
|
||||||
|
SG_LOG(SG_NETWORK, SG_INFO, "adding RR:" << recentlyRemoved.back().path);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#if defined (MIRROR_DEBUG)
|
||||||
|
SG_LOG(SG_NETWORK, SG_INFO, "saw remove of:" << child->getPath());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerSubtree(SGPropertyNode* node)
|
void registerSubtree(SGPropertyNode* node)
|
||||||
|
@ -228,7 +248,7 @@ using std::string;
|
||||||
std::set<SGPropertyNode*> newNodes;
|
std::set<SGPropertyNode*> newNodes;
|
||||||
std::set<SGPropertyNode*> changedNodes;
|
std::set<SGPropertyNode*> changedNodes;
|
||||||
std::set<PropertyId> removedNodes;
|
std::set<PropertyId> removedNodes;
|
||||||
|
|
||||||
PropertyId idForProperty(SGPropertyNode* prop)
|
PropertyId idForProperty(SGPropertyNode* prop)
|
||||||
{
|
{
|
||||||
auto it = idHash.find(prop);
|
auto it = idHash.find(prop);
|
||||||
|
@ -339,7 +359,7 @@ using std::string;
|
||||||
/// track recently removed nodes in case they are re-created imemdiately
|
/// track recently removed nodes in case they are re-created imemdiately
|
||||||
/// after with the same type, since we can make this much more efficient
|
/// after with the same type, since we can make this much more efficient
|
||||||
/// when sending over the wire.
|
/// when sending over the wire.
|
||||||
std::vector<RecentlyRemovedNode> recentlyRemoved;
|
std::vector<RemovedNode> recentlyRemoved;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
Loading…
Reference in a new issue