Changeset 536 for trunk


Ignore:
Timestamp:
01/17/17 19:15:37 (8 years ago)
Author:
epyon
Message:
  • ecs relationship tree
Location:
trunk/nv
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/nv/ecs/ecs.hh

    r530 r536  
    182182                        }
    183183
     184                        virtual void attach( handle_type parent, handle_type child )
     185                        {
     186                                m_handles.detach( child );
     187                                m_handles.attach( parent, child );
     188                        }
     189
     190                        handle_type get_parent( handle_type h ) const
     191                        {
     192                                return h ? m_handles.get_parent( h ) : handle_type();
     193                        }
     194
     195                        handle_type next( handle_type h ) const
     196                        {
     197                                return h ? m_handles.next( h ) : handle_type();
     198                        }
     199
     200                        handle_type first( handle_type h ) const
     201                        {
     202                                return h ? m_handles.first( h ) : handle_type();
     203                        }
     204
    184205                        void remove( handle_type h )
    185206                        {
     207                                handle_type ch = m_handles.first( h );
     208                                while ( handle_type r = ch )
     209                                {
     210                                        ch = m_handles.next( ch );
     211                                        remove( r );
     212                                }
    186213                                for ( auto c : m_components )
    187214                                        c->remove( h );
     
    208235                protected:
    209236
    210                         handle_manager< handle_type >               m_handles;
     237                        handle_tree_manager< handle_type >          m_handles;
    211238                        vector< component_interface* >              m_components;
    212239                        vector< receiver_interface* >               m_receivers;
     
    246273                        value_type& insert( handle_type h )
    247274                        {
    248                                 /*index_type i = */m_index.insert( h );
    249                                 //NV_ASSERT( i == m_data.size(), "Fail!" );
     275                                index_type i = m_index.insert( h );
     276                                NV_ASSERT( i == index_type( m_data.size() ), "Fail!" );
     277                                NV_UNUSED( i );
    250278                                m_data.emplace_back();
    251279                                return m_data.back();
     
    255283                        value_type& insert( handle_type h, Args&&... args )
    256284                        {
    257                                 /*index_type i = */m_index.insert( h );
    258                                 //NV_ASSERT( i == m_data.size(), "Fail!" );
     285                                index_type i = m_index.insert( h );
     286                                NV_ASSERT( i == index_type( m_data.size() ), "Fail!" );
     287                                NV_UNUSED( i );
    259288                                m_data.emplace_back( nv::forward<Args>( args )... );
    260289                                return m_data.back();
     
    302331                                return i >= 0 ? &( m_data[unsigned( i )] ) : nullptr;
    303332                        }
    304 
    305333
    306334                        virtual void remove( handle_type h )
  • trunk/nv/stl/handle_manager.hh

    r530 r536  
    9595                        value_type counter;
    9696                        index_type next_free;
    97 
     97                       
    9898                        index_entry() : counter( 0 ), next_free( NONE ) {}
    9999                };
     
    118118        };
    119119
     120        template < typename Handle, typename Index = sint32 >
     121        class handle_tree_manager
     122        {
     123                typedef Index index_type;
     124                static const index_type NONE = index_type( -1 );
     125                static const index_type USED = index_type( -2 );
     126        public:
     127
     128                typedef Handle handle_type;
     129                typedef typename handle_type::value_type value_type;
     130
     131                handle_tree_manager()
     132                        : m_first_free( NONE ), m_last_free( NONE ) {}
     133
     134                handle_type create_handle()
     135                {
     136                        typedef handle_operator<handle_type> hop;
     137                        value_type i = get_free_entry();
     138                        m_entries[i].counter++;
     139                        NV_ASSERT( m_entries[i].counter != 0, "Out of handles!" );
     140                        m_entries[i].next_free = USED;
     141                        return hop::create( i, m_entries[i].counter );
     142                }
     143
     144                void free_handle( handle_type h )
     145                {
     146                        remove( h );
     147                        value_type index = h.index();
     148                        NV_ASSERT( m_entries[index].next_free == USED, "Unused handle freed!" );
     149                        NV_ASSERT( m_entries[index].counter == handle_operator<handle_type>::get_counter( h ), "Handle corruption!" );
     150                        m_entries[index].next_free = NONE;
     151                        if ( m_last_free == NONE )
     152                        {
     153                                m_first_free = m_last_free = static_cast<index_type>( index );
     154                                return;
     155                        }
     156                        m_entries[static_cast<value_type>( m_last_free )].next_free = static_cast<index_type>( index );
     157                        m_last_free = static_cast<index_type>( index );
     158                }
     159
     160                void attach( handle_type parent, handle_type child )
     161                {
     162                        value_type pindex = parent.index();
     163                        value_type cindex = child.index();
     164                        NV_ASSERT( m_entries[cindex].parent == NONE, "Attach called on handle with parent!" );
     165                        m_entries[cindex].parent = pindex;
     166                        m_entries[cindex].next_sibling = m_entries[pindex].first_child;
     167                        m_entries[cindex].prev_sibling = NONE;
     168                        m_entries[pindex].first_child = cindex;
     169                }
     170
     171                handle_type get_parent( handle_type h ) const
     172                {
     173                        NV_ASSERT( is_valid( h ), "INVALID HANDLE" );
     174                        value_type pindex = m_entries[h.index()].parent;
     175                        typedef handle_operator<handle_type> hop;
     176                        return pindex == NONE ? handle_type() : hop::create( pindex, m_entries[pindex].counter );
     177                }
     178
     179                handle_type next( handle_type h ) const
     180                {
     181                        NV_ASSERT( is_valid( h ), "INVALID HANDLE" );
     182                        value_type nindex = m_entries[ h.index() ].next_sibling;
     183                        typedef handle_operator<handle_type> hop;
     184                        return nindex == NONE ? handle_type() : hop::create( nindex, m_entries[nindex].counter );
     185                }
     186
     187                handle_type first( handle_type h ) const
     188                {
     189                        NV_ASSERT( is_valid( h ), "INVALID HANDLE" );
     190                        value_type nindex = m_entries[h.index()].first_child;
     191                        typedef handle_operator<handle_type> hop;
     192                        return nindex == NONE ? handle_type() : hop::create( nindex, m_entries[nindex].counter );
     193                }
     194
     195
     196                void remove( handle_type h )
     197                {
     198                        NV_ASSERT( m_entries[h.index()].first_child == NONE, "Remove called on handle with children!" );
     199                        detach( h );
     200                }
     201
     202                void remove_and_orphan( handle_type h )
     203                {
     204                        detach( h );
     205                        value_type index = h.index();
     206                        while ( m_entries[index].first_child != NONE )
     207                        {
     208                                value_type child = m_entries[index].first_child;
     209                                m_entries[index].first_child  = m_entries[child].next_sibling;
     210                                m_entries[child].parent       = NONE;
     211                                m_entries[child].next_sibling = NONE;
     212                                m_entries[child].prev_sibling = NONE;
     213                        }
     214                }
     215
     216                void detach( handle_type h )
     217                {
     218                        value_type index      = h.index();
     219                        value_type pindex     = m_entries[index].parent;
     220                        value_type next_index = m_entries[index].next_sibling;
     221                        value_type prev_index = m_entries[index].prev_sibling;
     222                       
     223                        m_entries[index].parent       = NONE;
     224                        m_entries[index].next_sibling = NONE;
     225                        m_entries[index].prev_sibling = NONE;
     226
     227                        if ( pindex == NONE )
     228                        {
     229                                NV_ASSERT( next_index == NONE, "Hierarchy fail! next_index" );
     230                                NV_ASSERT( prev_index == NONE, "Hierarchy fail! prev_index" );
     231                                return;
     232                        }
     233                        if ( value_type( m_entries[pindex].first_child ) == index )
     234                        {
     235                                NV_ASSERT( prev_index == NONE, "Hierarchy fail! prev_index" );
     236                                m_entries[pindex].first_child = next_index;
     237                                if ( next_index == NONE ) // only child
     238                                        return;
     239                                m_entries[next_index].prev_sibling = NONE;
     240                        }
     241                        else
     242                        {
     243                                NV_ASSERT( prev_index != NONE, "Hierarchy fail! prev_index" );
     244                                if ( next_index != NONE )
     245                                        m_entries[next_index].prev_sibling = prev_index;
     246                                if ( prev_index != NONE )
     247                                        m_entries[prev_index].next_sibling = next_index;
     248                        }
     249                }
     250
     251                bool is_valid( handle_type h ) const
     252                {
     253                        typedef handle_operator<handle_type> hop;
     254                        if ( h.is_nil() ) return false;
     255                        if ( h.index() >= m_entries.size() ) return false;
     256                        const index_entry& entry = m_entries[h.index()];
     257                        return entry.next_free == USED && entry.counter == hop::get_counter( h );
     258                }
     259
     260                void clear()
     261                {
     262                        m_first_free = NONE;
     263                        m_last_free = NONE;
     264                        m_entries.clear();
     265                }
     266
     267        private:
     268                struct index_entry
     269                {
     270                        value_type counter;
     271                        index_type next_free;
     272
     273                        index_type parent;
     274                        index_type first_child;
     275                        index_type next_sibling;
     276                        index_type prev_sibling;
     277
     278                        index_entry()
     279                                : counter( 0 )
     280                                , next_free( NONE )
     281                                , parent( NONE )
     282                                , first_child( NONE )
     283                                , next_sibling( NONE )
     284                                , prev_sibling( NONE )
     285                        {}
     286                };
     287
     288                value_type get_free_entry()
     289                {
     290                        if ( m_first_free != NONE )
     291                        {
     292                                value_type result = static_cast<value_type>( m_first_free );
     293                                m_first_free = m_entries[result].next_free;
     294                                m_entries[result].next_free = USED;
     295                                if ( m_first_free == NONE ) m_last_free = NONE;
     296                                return result;
     297                        }
     298                        m_entries.emplace_back();
     299                        return value_type( m_entries.size() - 1 );
     300                }
     301
     302                index_type m_first_free;
     303                index_type m_last_free;
     304                vector< index_entry > m_entries;
     305        };
     306
     307
    120308}
    121309
Note: See TracChangeset for help on using the changeset viewer.