* improve performance of big maps loading, undo/redo dramatically
determinant factor is amount of nodes in one container
This commit is contained in:
parent
c0c9f49433
commit
812679236d
|
|
@ -58,6 +58,7 @@ const Type& get() const {
|
|||
|
||||
|
||||
/// \brief An adaptor to make std::list into a Unique Sequence - which cannot contain the same value more than once.
|
||||
/// It's illegal to modify inserted values directly!
|
||||
/// \param Value Uniquely identifies itself. Must provide a copy-constructor and an equality operator.
|
||||
template<typename Value>
|
||||
class UnsortedSet
|
||||
|
|
@ -69,6 +70,38 @@ typedef typename Values::iterator iterator;
|
|||
typedef typename Values::const_iterator const_iterator;
|
||||
typedef typename Values::reverse_iterator reverse_iterator;
|
||||
typedef typename Values::const_reverse_iterator const_reverse_iterator;
|
||||
private:
|
||||
struct Compare{
|
||||
using is_transparent = void;
|
||||
|
||||
bool operator()( const iterator& one, const iterator& other ) const {
|
||||
return *one < *other;
|
||||
}
|
||||
bool operator()( const Value& va, const iterator& it ) const {
|
||||
return va < *it;
|
||||
}
|
||||
bool operator()( const iterator& it, const Value& va ) const {
|
||||
return *it < va;
|
||||
}
|
||||
};
|
||||
std::set<iterator, Compare> m_set; // store sorted iterators for fast lookup
|
||||
void init_set(){ // only load set, when lookup is needed
|
||||
if( m_set.empty() )
|
||||
for( auto it = begin(); it != end(); ++it )
|
||||
m_set.emplace( it );
|
||||
}
|
||||
public:
|
||||
|
||||
UnsortedSet() = default;
|
||||
UnsortedSet( const UnsortedSet& other ) : m_values( other.m_values ), m_set(){
|
||||
}
|
||||
UnsortedSet( UnsortedSet&& ) noexcept = default;
|
||||
UnsortedSet& operator=( const UnsortedSet& other ){
|
||||
m_values = other.m_values;
|
||||
m_set.clear();
|
||||
return *this;
|
||||
}
|
||||
UnsortedSet& operator=( UnsortedSet&& ) noexcept = default;
|
||||
|
||||
iterator begin(){
|
||||
return m_values.begin();
|
||||
|
|
@ -103,23 +136,32 @@ std::size_t size() const {
|
|||
}
|
||||
void clear(){
|
||||
m_values.clear();
|
||||
m_set.clear();
|
||||
}
|
||||
|
||||
void swap( UnsortedSet& other ){
|
||||
std::swap( m_values, other.m_values );
|
||||
std::swap( m_set, other.m_set );
|
||||
}
|
||||
|
||||
iterator insert( const Value& value ){
|
||||
ASSERT_MESSAGE( find( value ) == end(), "UnsortedSet::insert: already added" );
|
||||
init_set();
|
||||
m_values.push_back( value );
|
||||
const bool inserted = m_set.emplace( --end() ).second;
|
||||
ASSERT_MESSAGE( inserted, "UnsortedSet::insert: already added" );
|
||||
return --end();
|
||||
}
|
||||
void erase( const Value& value ){
|
||||
iterator i = find( value );
|
||||
ASSERT_MESSAGE( i != end(), "UnsortedSet::erase: not found" );
|
||||
m_values.erase( i );
|
||||
init_set();
|
||||
const auto it = m_set.find( value );
|
||||
ASSERT_MESSAGE( it != m_set.end(), "UnsortedSet::erase: not found" );
|
||||
m_values.erase( *it );
|
||||
m_set.erase( it );
|
||||
}
|
||||
iterator find( const Value& value ){
|
||||
return std::find( begin(), end(), value );
|
||||
init_set();
|
||||
const auto it = m_set.find( value );
|
||||
return it == m_set.end()? m_values.end() : *it;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -274,7 +316,7 @@ void erase( const Value& value ){
|
|||
m_values.erase( i );
|
||||
}
|
||||
iterator find( const Value& value ){
|
||||
return std::find( begin(), end(), value );
|
||||
return m_values.find( value );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -745,6 +745,10 @@ class GraphTreeNode
|
|||
{
|
||||
typedef std::map<std::pair<CopiedString, scene::Node*>, GraphTreeNode*> ChildNodes;
|
||||
ChildNodes m_childnodes;
|
||||
|
||||
std::list<char> m_list; // dummy list for child index identification
|
||||
std::list<char>::const_iterator m_parentListIterator; // iterator from parent's list
|
||||
bool m_searchFromEnd = false; //silly optimization
|
||||
public:
|
||||
Reference<scene::Instance> m_instance;
|
||||
GraphTreeNode* m_parent;
|
||||
|
|
@ -761,6 +765,11 @@ GraphTreeNode( scene::Instance& instance ) : m_instance( instance ), m_parent( 0
|
|||
m_instance.get().setChildSelectedChangedCallback( Callback() );
|
||||
ASSERT_MESSAGE( empty(), "GraphTreeNode::~GraphTreeNode: memory leak" );
|
||||
}
|
||||
GraphTreeNode() = delete;
|
||||
GraphTreeNode( const GraphTreeNode& ) = delete;
|
||||
GraphTreeNode( GraphTreeNode&& ) noexcept = delete;
|
||||
GraphTreeNode& operator=( const GraphTreeNode& ) = delete;
|
||||
GraphTreeNode& operator=( GraphTreeNode&& ) noexcept = delete;
|
||||
|
||||
iterator begin(){
|
||||
return m_childnodes.begin();
|
||||
|
|
@ -775,25 +784,30 @@ size_type size() const {
|
|||
bool empty() const {
|
||||
return m_childnodes.empty();
|
||||
}
|
||||
// may not be called on the root node!
|
||||
int getIndex() const {
|
||||
const int idx = m_parent->m_searchFromEnd?
|
||||
m_parent->m_list.size() - std::distance( m_parentListIterator, m_parent->m_list.cend() ) :
|
||||
std::distance( m_parent->m_list.cbegin(), m_parentListIterator );
|
||||
m_parent->m_searchFromEnd = idx * 2 > int( m_parent->size() );
|
||||
return idx;
|
||||
}
|
||||
|
||||
iterator insert( const value_type& value ){
|
||||
iterator i = m_childnodes.insert( value ).first;
|
||||
( *i ).second->m_parent = this;
|
||||
const auto pos = std::next( i ) == end()? m_list.end() : std::next( i )->second->m_parentListIterator;
|
||||
i->second->m_parentListIterator = m_list.insert( pos, 'a' );
|
||||
return i;
|
||||
}
|
||||
void erase( iterator i ){
|
||||
m_list.erase( i->second->m_parentListIterator );
|
||||
m_childnodes.erase( i );
|
||||
}
|
||||
iterator find( const key_type& key ){
|
||||
return m_childnodes.find( key );
|
||||
}
|
||||
|
||||
void swap( GraphTreeNode& other ){
|
||||
std::swap( m_parent, other.m_parent );
|
||||
std::swap( m_childnodes, other.m_childnodes );
|
||||
std::swap( m_instance, other.m_instance );
|
||||
}
|
||||
|
||||
void rowChanged(){
|
||||
graph_tree_model_row_changed( *this );
|
||||
}
|
||||
|
|
@ -884,15 +898,7 @@ static GtkTreePath* graph_tree_model_get_path( GtkTreeModel* tree_model, GtkTree
|
|||
|
||||
for ( GraphTreeNode* node = ( *graph_iterator_read_tree_iter( iter ) ).second; node != graph; node = node->m_parent )
|
||||
{
|
||||
std::size_t index = 0;
|
||||
for ( GraphTreeNode::iterator i = node->m_parent->begin(); i != node->m_parent->end(); ++i, ++index )
|
||||
{
|
||||
if ( ( *i ).second == node ) {
|
||||
gtk_tree_path_prepend_index( path, gint( index ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_MESSAGE( index != node->m_parent->size(), "error resolving tree path" );
|
||||
gtk_tree_path_prepend_index( path, gint( node->getIndex() ) );
|
||||
}
|
||||
|
||||
return path;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user