Maik JUSTUS:
""" - make every node maintain list of properties that link to it - add functions to erase node by address from hash bucket/entry in their path caches, so that all references can be removed - if a node is removed, it (and all children, grandchildren, ...) calls all linked properties to remove them from their path-cache This fixes problems with the aerotow over multiplayer and maybe some other problems, where nodes are queried by name. """
This commit is contained in:
+62
-2
@@ -910,6 +910,21 @@ SGPropertyNode::getChildren (const char * name) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove this node from all nodes that link to it in their path cache.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
SGPropertyNode::remove_from_path_caches ()
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < _linkedNodes.size(); i++)
|
||||||
|
_linkedNodes[i]->erase(this);
|
||||||
|
|
||||||
|
_linkedNodes.clear();
|
||||||
|
for (unsigned int i = 0; i < _children.size(); ++i)
|
||||||
|
_children[i]->remove_from_path_caches();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove child by position.
|
* Remove child by position.
|
||||||
*/
|
*/
|
||||||
@@ -927,8 +942,8 @@ SGPropertyNode::removeChild (int pos, bool keep)
|
|||||||
if (keep) {
|
if (keep) {
|
||||||
_removedChildren.push_back(node);
|
_removedChildren.push_back(node);
|
||||||
}
|
}
|
||||||
if (_path_cache)
|
|
||||||
_path_cache->erase(node->getName()); // EMH - TODO: Take "index" into account!
|
node->remove_from_path_caches();
|
||||||
node->setAttribute(REMOVED, true);
|
node->setAttribute(REMOVED, true);
|
||||||
node->clearValue();
|
node->clearValue();
|
||||||
fireChildRemoved(node);
|
fireChildRemoved(node);
|
||||||
@@ -967,6 +982,24 @@ SGPropertyNode::removeChildren (const char * name, bool keep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a linked node.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
SGPropertyNode::remove_linked_node (hash_table * node)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < _linkedNodes.size(); i++) {
|
||||||
|
if (_linkedNodes[i] == node) {
|
||||||
|
vector<hash_table *>::iterator it = _linkedNodes.begin();
|
||||||
|
it += i;
|
||||||
|
_linkedNodes.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
SGPropertyNode::getDisplayName (bool simplify) const
|
SGPropertyNode::getDisplayName (bool simplify) const
|
||||||
{
|
{
|
||||||
@@ -2210,6 +2243,20 @@ SGPropertyNode::hash_table::bucket::erase (const char * key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SGPropertyNode::hash_table::bucket::erase (SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _length; i++) {
|
||||||
|
if (_entries[i]->get_value() == node) {
|
||||||
|
for (++i; i < _length; i++) {
|
||||||
|
_entries[i-1] = _entries[i];
|
||||||
|
}
|
||||||
|
_length--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SGPropertyNode::hash_table::hash_table ()
|
SGPropertyNode::hash_table::hash_table ()
|
||||||
: _data_length(0),
|
: _data_length(0),
|
||||||
@@ -2254,6 +2301,7 @@ SGPropertyNode::hash_table::put (const char * key, SGPropertyNode * value)
|
|||||||
}
|
}
|
||||||
entry * e = _data[index]->get_entry(key, true);
|
entry * e = _data[index]->get_entry(key, true);
|
||||||
e->set_value(value);
|
e->set_value(value);
|
||||||
|
value->add_linked_node(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2264,7 +2312,19 @@ SGPropertyNode::hash_table::erase (const char * key)
|
|||||||
unsigned int index = hashcode(key) % _data_length;
|
unsigned int index = hashcode(key) % _data_length;
|
||||||
if (_data[index] == 0)
|
if (_data[index] == 0)
|
||||||
return;
|
return;
|
||||||
|
_data[index]->get_entry(key, true)->get_value()->remove_linked_node(this);
|
||||||
_data[index]->erase(key);
|
_data[index]->erase(key);
|
||||||
|
_data[index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SGPropertyNode::hash_table::erase (SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
for (unsigned int d = 0; d < _data_length; d++)
|
||||||
|
if (_data[d] && _data[d]->erase(node))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
|
|||||||
+19
-3
@@ -1183,6 +1183,12 @@ private:
|
|||||||
void trace_write () const;
|
void trace_write () const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove this node from all nodes that link to it in their path cache.
|
||||||
|
*/
|
||||||
|
void remove_from_path_caches();
|
||||||
|
|
||||||
|
|
||||||
class hash_table;
|
class hash_table;
|
||||||
|
|
||||||
int _index;
|
int _index;
|
||||||
@@ -1193,6 +1199,7 @@ private:
|
|||||||
SGPropertyNode * _parent;
|
SGPropertyNode * _parent;
|
||||||
vector<SGPropertyNode_ptr> _children;
|
vector<SGPropertyNode_ptr> _children;
|
||||||
vector<SGPropertyNode_ptr> _removedChildren;
|
vector<SGPropertyNode_ptr> _removedChildren;
|
||||||
|
vector<hash_table *> _linkedNodes;
|
||||||
mutable string _path;
|
mutable string _path;
|
||||||
mutable string _buffer;
|
mutable string _buffer;
|
||||||
hash_table * _path_cache;
|
hash_table * _path_cache;
|
||||||
@@ -1223,9 +1230,16 @@ private:
|
|||||||
vector <SGPropertyChangeListener *> * _listeners;
|
vector <SGPropertyChangeListener *> * _listeners;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register/unregister node that links to this node in its path cache.
|
||||||
|
*/
|
||||||
|
void add_linked_node (hash_table * node) { _linkedNodes.push_back(node); }
|
||||||
|
bool remove_linked_node (hash_table * node);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A very simple hash table with no remove functionality.
|
* A very simple hash table.
|
||||||
*/
|
*/
|
||||||
class hash_table {
|
class hash_table {
|
||||||
public:
|
public:
|
||||||
@@ -1255,7 +1269,8 @@ private:
|
|||||||
bucket ();
|
bucket ();
|
||||||
~bucket ();
|
~bucket ();
|
||||||
entry * get_entry (const char * key, bool create = false);
|
entry * get_entry (const char * key, bool create = false);
|
||||||
void erase(const char * key);
|
void erase (const char * key);
|
||||||
|
bool erase (SGPropertyNode * node);
|
||||||
private:
|
private:
|
||||||
int _length;
|
int _length;
|
||||||
entry ** _entries;
|
entry ** _entries;
|
||||||
@@ -1267,7 +1282,8 @@ private:
|
|||||||
~hash_table ();
|
~hash_table ();
|
||||||
SGPropertyNode * get (const char * key);
|
SGPropertyNode * get (const char * key);
|
||||||
void put (const char * key, SGPropertyNode * value);
|
void put (const char * key, SGPropertyNode * value);
|
||||||
void erase(const char * key);
|
void erase (const char * key);
|
||||||
|
bool erase (SGPropertyNode * node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int hashcode (const char * key);
|
unsigned int hashcode (const char * key);
|
||||||
|
|||||||
Reference in New Issue
Block a user