Index: /trunk/nv/ecs/component.hh
===================================================================
--- /trunk/nv/ecs/component.hh	(revision 542)
+++ /trunk/nv/ecs/component.hh	(revision 543)
@@ -136,4 +136,31 @@
 			}
 
+			void remove_by_index( index_type i )
+			{
+				if ( i > size() ) return;
+				destroy( &m_data[i] );
+				index_type dead_eindex = m_index.remove_swap_by_index( i );
+				if ( dead_eindex == -1 ) return;
+				if ( dead_eindex != static_cast<index_type>( m_data.size() - 1 ) )
+				{
+					m_data[unsigned( dead_eindex )] = move( m_data.back() );
+				}
+				m_data.pop_back();
+			}
+
+			template < typename F >
+			void remove_if( F f )
+			{
+				uint32 i = 0;
+				while ( i < size() )
+				{
+					auto& md = m_data[i];
+					if ( f( md ) )
+						remove_by_index( i );
+					else
+						++i;
+				}
+			}
+
 			virtual void destroy( value_type* )
 			{
@@ -146,6 +173,4 @@
 			}
 			
-			inline handle_type _get_handle( index_type i ) const { return m_index.get_handle( i ); }
-
 			inline const value_type& operator[] ( index_type i ) const { return m_data[i]; }
 			inline value_type& operator[] ( index_type i ) { return m_data[i]; }
@@ -159,5 +184,5 @@
 			inline const_iterator  end()  const { return m_data.end(); }
 
-			//inline virtual component_storage* storage() { return &m_data; }
+			inline virtual component_storage* storage() { return &m_data; }
 		protected:
 			ecs_type&        m_ecs;
Index: /trunk/nv/ecs/component_storage.hh
===================================================================
--- /trunk/nv/ecs/component_storage.hh	(revision 542)
+++ /trunk/nv/ecs/component_storage.hh	(revision 543)
@@ -156,5 +156,5 @@
 			return ( component_storage_handler< Component >* )storage;
 		}
-
+		/*
 		template < typename Handle, typename Component >
 		class index_storage 
@@ -237,6 +237,4 @@
 
 			}
-
-			inline handle_type get_handle( index_type i ) const { return m_handles[unsigned( i )]; }
 
 			inline const value_type& operator[] ( index_type i ) const { return m_data[i]; }
@@ -428,5 +426,5 @@
 
 		class direct_storage;
-		/*
+		
 		template < typename Handle, typename Component >
 		class hash_storage
Index: /trunk/nv/ecs/ecs.hh
===================================================================
--- /trunk/nv/ecs/ecs.hh	(revision 542)
+++ /trunk/nv/ecs/ecs.hh	(revision 543)
@@ -36,4 +36,40 @@
 	namespace ecs
 	{
+
+		namespace detail
+		{
+			template<typename, typename T>
+			struct has_update
+			{
+				static_assert( nv::integral_constant<T, false>::value, "Second template parameter needs to be of function type." );
+			};
+
+			template< typename C, typename Ret, typename... Args >
+			struct has_update<C, Ret( Args... )>
+			{
+			private:
+				template<typename T>
+				static constexpr auto check( T* )
+					-> typename nv::is_same< decltype( nv::declval<T>().update( nv::declval<Args>()... ) ), Ret >::type;
+
+				template<typename>
+				static constexpr nv::false_type check( ... );
+
+				typedef decltype( check<C>( 0 ) ) type;
+
+			public:
+				static constexpr bool value = type::value;
+			};
+		}
+
+		template < typename E, typename S, typename T >
+		using has_ecs_update = detail::has_update<S, void( E&, T ) >;
+
+		template < typename S, typename C, typename T >
+		using has_component_update = detail::has_update<S, void( C&, T ) >;
+
+		template < typename E, typename S, typename C, typename T >
+		using has_ecs_component_update = detail::has_update<S, void( E&, C&, T ) >;
+
 		template < typename S, typename C, typename M >
 		using has_component_message = detail::has_message<S, void( const M&, C& ) >;
@@ -44,5 +80,4 @@
 		template < typename E, typename S, typename M >
 		using has_ecs_message = detail::has_message<S, void( const M&, E& ) >;
-
 
 		template < typename Handle, typename MessageList, typename Time = f32 >
@@ -57,5 +92,5 @@
 			using base_type::message;
 
-
+			using update_handler = function< void( time_type ) >;
 
 			class component_interface
@@ -68,5 +103,5 @@
 				virtual void* get_raw( handle_type h ) = 0;
 				virtual const void* get_raw( handle_type h ) const = 0;
-//				virtual component_storage* storage() = 0;
+				virtual component_storage* storage() = 0;
 			};
 
@@ -81,10 +116,4 @@
 					return *this;
 				}
-// 				enumerator operator++ ( int )
-// 				{
-// 					auto result = *this;
-// 					base_class::m_value = m_ecs.next( base_class::m_value );
-// 					return result;
-// 				}
 			private:
 				const ecs& m_ecs;
@@ -115,7 +144,5 @@
 				}
 				Component& operator* () { return *m_component; }
-				Component* operator-> () { return &m_component; }
 				const Component& operator* () const { return *m_component; }
-				const Component* operator-> () const { return &m_component; }
 				bool operator== ( const component_enumerator& rhs ) const
 				{
@@ -149,4 +176,7 @@
 				register_handler< Handler >( name, (Handler*)c );
 				register_component_messages< Handler, Component >( (Handler*)( c ), message_list{} );
+				register_ecs_component_update< Handler, Component >( (Handler*)( c ) );
+				register_component_update< Handler, Component >( (Handler*)( c ) );
+				register_ecs_update< Handler >( (Handler*)( c ) );
 //				auto s = c->storage();
 // 				m_cstorage.push_back( s );
@@ -165,4 +195,6 @@
 				for ( auto c : m_components )
 					c->update( dtime );
+				for ( auto u : m_update_handlers )
+					u( dtime );
 			}
 
@@ -294,6 +326,6 @@
 			void register_component_messages( System* h, List<Messages...>&& )
 			{
-				int unused_0[] = { ( register_component_message<System,Components,Messages>( h ), 0 )... };
-				int unused_1[] = { ( register_ecs_component_message<System,Components,Messages>( h ), 0 )... };
+				int unused_0[] = { ( register_ecs_component_message<System,Components,Messages>( h ), 0 )... };
+				int unused_1[] = { ( register_component_message<System,Components,Messages>( h ), 0 )... };
 				int unused_2[] = { ( register_ecs_message<System,Messages>( h ), 0 )... };
 			}
@@ -349,5 +381,57 @@
 			register_ecs_message( System* ) {}
 
-
+			template < typename System >
+			typename enable_if< has_ecs_update< this_type, System, time_type >::value, void >::type
+			register_ecs_update( System* s )
+			{
+				register_update( [=] ( time_type dtime )
+				{
+					s->update( *this, dtime );
+				} );
+			}
+
+			template < typename System, typename Components >
+			typename enable_if< has_component_update< System, Components, time_type >::value, void >::type
+			register_component_update( System* s )
+			{
+				component_interface* ci = get_interface<Components>();
+				component_storage_handler<Components>* storage = storage_cast<Components>( ci->storage() );
+				register_update( [=] ( time_type dtime )
+				{
+					for ( auto& c : *storage )
+						s->update( c, dtime );
+				} );
+			}
+
+			template < typename System, typename Components >
+			typename enable_if< has_ecs_component_update< this_type, System, Components, time_type >::value, void >::type
+			register_ecs_component_update( System* s )
+			{
+				component_interface* ci = get_interface<Components>();
+				component_storage_handler<Components>* storage = storage_cast<Components>( ci->storage() );
+				register_update( [=] ( time_type dtime )
+				{
+					for ( auto& c : *storage )
+						s->update( *this, c, dtime );
+				} );
+			}
+
+
+			template < typename System >
+			typename enable_if< !has_ecs_update< this_type, System, time_type >::value, void >::type
+			register_ecs_update( System* ) {}
+
+			template < typename System, typename Components >
+			typename enable_if< !has_component_message< System, Components, time_type >::value, void >::type
+			register_component_update( System* ) {}
+
+			template < typename System, typename Components >
+			typename enable_if< !has_ecs_component_update< this_type, System, Components, time_type >::value, void >::type
+			register_ecs_component_update( System* ) {}
+
+			void register_update( update_handler&& handler )
+			{
+				m_update_handlers.push_back( handler );
+			}
 
 			handle_tree_manager< handle_type >          m_handles;
@@ -355,4 +439,6 @@
 			hash_store< thash64, component_interface* > m_component_map;
 			hash_store< shash64, component_interface* > m_component_map_by_name;
+			vector< update_handler >                    m_update_handlers;
+
 // 			vector< component_storage* >                m_cstorage;
 // 			hash_store< thash64, component_storage* >   m_cmap;
Index: /trunk/nv/engine/particle_engine.hh
===================================================================
--- /trunk/nv/engine/particle_engine.hh	(revision 542)
+++ /trunk/nv/engine/particle_engine.hh	(revision 543)
@@ -149,4 +149,5 @@
 		~particle_engine();
 	private:
+		void release( particle_system_info* system );
 		void clear();
 		void register_standard_emitters();
Index: /trunk/nv/engine/particle_group.hh
===================================================================
--- /trunk/nv/engine/particle_group.hh	(revision 542)
+++ /trunk/nv/engine/particle_group.hh	(revision 543)
@@ -113,4 +113,5 @@
 		bool unref( particle_group group );
 	protected:
+		void release( particle_group_info* group );
 		void clear();
 
Index: /trunk/nv/fmod/fmod_audio.hh
===================================================================
--- /trunk/nv/fmod/fmod_audio.hh	(revision 542)
+++ /trunk/nv/fmod/fmod_audio.hh	(revision 543)
@@ -42,4 +42,6 @@
 			virtual ~audio();
 		private:
+			void release( sound_info* info );
+
 			handle_store< sound_info, sound >     m_sounds;
 			vec3                                  m_position;
Index: /trunk/nv/gl/gl_context.hh
===================================================================
--- /trunk/nv/gl/gl_context.hh	(revision 542)
+++ /trunk/nv/gl/gl_context.hh	(revision 543)
@@ -90,4 +90,7 @@
 
 	protected:
+		void release( gl_vertex_array_info* va );
+		void release( gl_framebuffer_info* f );
+
 		void bind( program p );
 		void bind( vertex_array va );
Index: /trunk/nv/gl/gl_device.hh
===================================================================
--- /trunk/nv/gl/gl_device.hh	(revision 542)
+++ /trunk/nv/gl/gl_device.hh	(revision 543)
@@ -73,4 +73,10 @@
 		virtual ~gl_device();
 	protected:
+
+		void release( gl_buffer_info* b );
+		void release( gl_texture_info* t );
+		void release( gl_program_info* p );
+		void release( gl_shader_info* s );
+
 		gl_texture_info* get_full_texture_info( texture t );
 		gl_buffer_info* get_full_buffer_info( buffer t );
Index: /trunk/nv/sdl/sdl_audio.hh
===================================================================
--- /trunk/nv/sdl/sdl_audio.hh	(revision 542)
+++ /trunk/nv/sdl/sdl_audio.hh	(revision 543)
@@ -40,4 +40,6 @@
 			virtual ~audio();
 		private:
+			void release( sound_info* info );
+
 			vec3                                  m_position;
 			vec3                                  m_forward;
Index: /trunk/nv/stl/handle_store.hh
===================================================================
--- /trunk/nv/stl/handle_store.hh	(revision 542)
+++ /trunk/nv/stl/handle_store.hh	(revision 543)
@@ -84,6 +84,4 @@
 		}
 
-		handle_type get_handle( index_type i ) const { return m_index.get_handle( i ); }
-
 		const value_type& operator[] ( index_type i ) const { return m_data[i]; }
 		value_type& operator[] ( index_type i ) { return m_data[i]; }
@@ -116,8 +114,11 @@
 		typedef typename storage::const_reference const_reference;
 
+		static const index_type INVALID = index_type( -1 );
+
 		unpacked_indexed_array() {}
 		unpacked_indexed_array( uint32 reserve )
 		{
 			m_data.reserve( reserve );
+			m_indices.reserve( reserve );
 		}
 
@@ -126,5 +127,5 @@
 			NV_ASSERT( !exists( h ), "Reinserting handle!" );
 			resize_to( index_type( h.index() ) );
-			m_handles[h.index()] = h;
+			m_indices[h.index()] = h.index();
 			return &( m_data[h.index()] );
 		}
@@ -133,5 +134,5 @@
 		{
 			if ( h.is_nil() || h.index() >= m_data.size() ) return false;
-			return m_handles[h.index()].is_valid();
+			return m_indices[h.index()] != INVALID;
 		}
 
@@ -152,5 +153,5 @@
 		void remove( handle h )
 		{
-			m_handles[h.index()] = handle();
+			m_indices[h.index()] = INVALID;
 		}
 
@@ -158,8 +159,6 @@
 		{
 			m_data.clear();
-			m_handles.clear();
-		}
-
-		handle get_handle( index_type i ) const { return m_handles[unsigned( i )]; }
+			m_indices.clear();
+		}
 
 		const value_type& operator[] ( index_type i ) const { return m_data[i]; }
@@ -178,5 +177,5 @@
 		void resize_to( index_type i )
 		{
-			index_type size = index_type( m_handles.size() );
+			index_type size = index_type( m_indices.size() );
 			if ( i >= size )
 			{
@@ -184,10 +183,10 @@
 				while ( i >= size ) size = size * 2;
 				m_data.resize( static_cast<size_t>( size ) );
-				m_handles.resize( static_cast<size_t>( size ) );
+				m_indices.resize( static_cast<size_t>( size ), INVALID );
 			}
 		}
 
 		vector< T >          m_data;
-		vector< handle >     m_handles;
+		vector< index_type > m_indices;
 	};
 
@@ -241,5 +240,10 @@
 		}
 
-		handle get_handle( index_type i ) const { return m_data.get_handle( i ); }
+		void clear()
+		{
+			m_data.clear();
+			m_indexes.clear();
+		}
+
 		const value_type& operator[] ( index_type i ) const { return m_data[unsigned( i )]; }
 		value_type& operator[] ( index_type i ) { return m_data[unsigned( i )]; }
Index: /trunk/nv/stl/index_table.hh
===================================================================
--- /trunk/nv/stl/index_table.hh	(revision 542)
+++ /trunk/nv/stl/index_table.hh	(revision 543)
@@ -25,5 +25,5 @@
 		typename Index = sint32
 	>
-		class index_table
+	class index_table
 	{
 	public:
@@ -43,5 +43,5 @@
 			index_type lindex = m_handles.size();
 			m_indexes[h.index()] = index_type( lindex );
-			m_handles.push_back( h );
+			m_handles.push_back( h.index() );
 			return lindex;
 		}
@@ -63,10 +63,10 @@
 			if ( h.is_nil() || h.index() >= m_indexes.size() || m_indexes[h.index()] == -1 )
 				return -1;
-			handle_type swap_handle = m_handles.back();
-			index_type  dead_eindex = m_indexes[h.index()];
-			if ( dead_eindex != static_cast<index_type>( m_handles.size() - 1 ) )
-			{
-				m_handles[unsigned( dead_eindex )] = swap_handle;
-				m_indexes[swap_handle.index()] = dead_eindex;
+			index_type swap_handle = m_handles.back();
+			index_type dead_eindex = m_indexes[h.index()];
+			if ( dead_eindex != static_cast<index_type>( m_handles.size() - 1 ) )
+			{
+				m_handles[unsigned( dead_eindex )] = swap_handle;
+				m_indexes[swap_handle] = dead_eindex;
 			}
 			m_handles.pop_back();
@@ -75,18 +75,18 @@
 		}
 
-// 		index_type remove_swap( index_type dead_eindex )
-// 		{
-// 			if ( uint32( dead_eindex ) >= m_handles.size() ) return -1;
-// 			handle_type h = m_handles[dead_eindex];
-// 			handle_type swap_handle = m_handles.back();
-// 			if ( dead_eindex != static_cast<index_type>( m_handles.size() - 1 ) )
-// 			{
-// 				m_handles[unsigned( dead_eindex )] = swap_handle;
-// 				m_indexes[swap_handle.index()] = dead_eindex;
-// 			}
-// 			m_handles.pop_back();
-// 			m_indexes[h.index()] = -1;
-// 			return dead_eindex;
-// 		}
+		index_type remove_swap_by_index( index_type dead_eindex )
+		{
+			if ( uint32( dead_eindex ) >= m_handles.size() ) return -1;
+			index_type h = m_handles[dead_eindex];
+			index_type swap_handle = m_handles.back();
+			if ( dead_eindex != static_cast<index_type>( m_handles.size() - 1 ) )
+			{
+				m_handles[unsigned( dead_eindex )] = swap_handle;
+				m_indexes[swap_handle] = dead_eindex;
+			}
+			m_handles.pop_back();
+			m_indexes[h] = -1;
+			return dead_eindex;
+		}
 
 
@@ -96,6 +96,4 @@
 			m_indexes.clear();
 		}
-
-		handle_type get_handle( index_type i ) const { return m_handles[unsigned( i )]; }
 
 		uint32 size() const { return m_handles.size(); }
@@ -113,6 +111,6 @@
 		}
 
-		vector< handle_type > m_handles;
-		vector< index_type >  m_indexes;
+		vector< index_type > m_handles;
+		vector< index_type > m_indexes;
 	};
 
@@ -135,8 +133,8 @@
 		index_type insert( handle_type h )
 		{
-			NV_ASSERT( m_indexes.find( h ) == m_indexes.end(), "Reinserting handle!" );
+			NV_ASSERT( m_indexes.find( h.index() ) == m_indexes.end(), "Reinserting handle!" );
 			index_type lindex = m_handles.size();
-			m_indexes[h] = index_type( lindex );
-			m_handles.push_back( h );
+			m_indexes[h.index()] = index_type( lindex );
+			m_handles.push_back( h.index() );
 			return lindex;
 		}
@@ -144,5 +142,5 @@
 		bool exists( handle_type h ) const
 		{
-			auto ih = m_indexes.find( h );
+			auto ih = m_indexes.find( h.index() );
 			return ( ih != m_indexes.end() );
 		}
@@ -150,5 +148,5 @@
 		index_type get( handle_type h ) const
 		{
-			auto ih = m_indexes.find( h );
+			auto ih = m_indexes.find( h.index() );
 			if ( ih == m_indexes.end() ) return -1;
 			return ih->second;
@@ -158,8 +156,23 @@
 		{
 			if ( h.is_nil() ) return -1;
-			auto ih = m_indexes.find( h );
+			auto ih = m_indexes.find( h.index() );
 			if ( ih == m_indexes.end() || ih->second == index_type(-1) ) return -1;
-			handle_type swap_handle = m_handles.back();
-			index_type  dead_eindex = ih->second;
+			index_type swap_handle = m_handles.back();
+			index_type dead_eindex = ih->second;
+			if ( dead_eindex != static_cast<index_type>( m_handles.size() - 1 ) )
+			{
+				m_handles[unsigned( dead_eindex )] = swap_handle;
+				m_indexes[swap_handle] = dead_eindex;
+			}
+			m_handles.pop_back();
+			m_indexes.erase( h.index() );
+			return dead_eindex;
+		}
+
+		index_type remove_swap( index_type dead_eindex )
+		{
+			if ( uint32( dead_eindex ) >= m_handles.size() ) return -1;
+			index_type h = m_handles[dead_eindex];
+			index_type swap_handle = m_handles.back();
 			if ( dead_eindex != static_cast<index_type>( m_handles.size() - 1 ) )
 			{
@@ -171,19 +184,4 @@
 			return dead_eindex;
 		}
-
-// 		index_type remove_swap( index_type dead_eindex )
-// 		{
-// 			if ( uint32( dead_eindex ) >= m_handles.size() ) return -1;
-// 			handle_type h = m_handles[dead_eindex];
-// 			handle_type swap_handle = m_handles.back();
-// 			if ( dead_eindex != static_cast<index_type>( m_handles.size() - 1 ) )
-// 			{
-// 				m_handles[unsigned( dead_eindex )] = swap_handle;
-// 				m_indexes[swap_handle] = dead_eindex;
-// 			}
-// 			m_handles.pop_back();
-// 			m_indexes.erase( h );
-// 			return dead_eindex;
-// 		}
 
 
@@ -194,14 +192,13 @@
 		}
 
-		handle_type get_handle( index_type i ) const { return m_handles[unsigned( i )]; }
-
 		uint32 size() const { return m_handles.size(); }
 
 	private:
 
-		vector< handle_type > m_handles;
-		hash_map< handle_type, index_type > m_indexes;
+		vector< index_type > m_handles;
+		hash_map< index_type, index_type > m_indexes;
 	};
 
+
 }
 
Index: /trunk/src/engine/particle_engine.cc
===================================================================
--- /trunk/src/engine/particle_engine.cc	(revision 542)
+++ /trunk/src/engine/particle_engine.cc	(revision 543)
@@ -350,8 +350,18 @@
 }
 
+void nv::particle_engine::release( particle_system_info* info )
+{
+	if ( info )
+	{
+		m_pgm->unref( info->group );
+		delete[] info->particles;
+	}
+}
+
 void nv::particle_engine::clear()
 {
-	while ( m_systems.size() > 0 )
-		release( m_systems.get_handle( 0 ) );
+	for ( auto& s : m_systems )
+		release( &s );
+	m_systems.clear();
 	if ( m_pgm )
 		m_pgm->reset();
@@ -363,9 +373,7 @@
 void nv::particle_engine::release( particle_system system )
 {
-	particle_system_info* info = m_systems.get( system );
-	if ( info )
-	{
-		m_pgm->unref( info->group );
-		delete[] info->particles;
+	if ( particle_system_info* info = m_systems.get( system ) )
+	{
+		release( info );
 		m_systems.destroy( system );
 	}
Index: /trunk/src/engine/particle_group.cc
===================================================================
--- /trunk/src/engine/particle_group.cc	(revision 542)
+++ /trunk/src/engine/particle_group.cc	(revision 543)
@@ -33,9 +33,7 @@
 void particle_group_manager::release( particle_group group )
 {
-	particle_group_info* info = m_groups.get( group );
-	if ( info )
-	{
-		delete[] info->quads;
-		m_context->release( info->vtx_array );
+	if ( particle_group_info* info = m_groups.get( group ) )
+	{
+		release( info );
 		m_groups.destroy( group );
 	}
@@ -194,4 +192,13 @@
 }
 
+void nv::particle_group_manager::release( particle_group_info* info )
+{
+	if ( info )
+	{
+		delete[] info->quads;
+		m_context->release( info->vtx_array );
+	}
+}
+
 particle_group_manager::~particle_group_manager()
 {
@@ -201,6 +208,7 @@
 void particle_group_manager::clear()
 {
-	while ( m_groups.size() > 0 )
-		release( m_groups.get_handle( 0 ) );
+	for ( auto& g : m_groups )
+		release( &g );
+	m_groups.clear();
 }
 
Index: /trunk/src/fmod/fmod_audio.cc
===================================================================
--- /trunk/src/fmod/fmod_audio.cc	(revision 542)
+++ /trunk/src/fmod/fmod_audio.cc	(revision 543)
@@ -107,9 +107,12 @@
 {
 	sound_info* info = m_sounds.get( a_sound );
+	release( info );
+	m_sounds.destroy( a_sound );
+}
+
+void nv::fmod::audio::release( sound_info* info )
+{
 	if ( info )
-	{
 		FMOD_Sound_Release( static_cast<FMOD_SOUND*>( info->fmod_sound ) );
-		m_sounds.destroy( a_sound );
-	}
 }
 
@@ -146,6 +149,7 @@
 fmod::audio::~audio()
 {
-	while ( m_sounds.size() > 0 )
-		release( m_sounds.get_handle(0) );
+	for ( auto& s : m_sounds )
+		release( &s );
+	m_sounds.clear();
 	FMOD_System_Release( static_cast<FMOD_SYSTEM*>( m_system ) );
 }
Index: /trunk/src/gl/gl_context.cc
===================================================================
--- /trunk/src/gl/gl_context.cc	(revision 542)
+++ /trunk/src/gl/gl_context.cc	(revision 543)
@@ -97,15 +97,22 @@
 void nv::gl_context::release( vertex_array va )
 {
-	gl_vertex_array_info* info = m_vertex_arrays.get( va );
+	if ( gl_vertex_array_info* info = m_vertex_arrays.get( va ) )
+	{
+		release( info );
+		m_vertex_arrays.destroy( va );
+	}
+}
+
+void nv::gl_context::release( gl_vertex_array_info* info )
+{
 	if ( info )
 	{
 		for ( uint32 i = 0; i < info->count; ++i )
 		{
-			if ( info->attr[i].owner ) 
+			if ( info->attr[i].owner )
 				release( info->attr[i].vbuffer );
 		}
-		if ( info->index.is_valid() && info->index_owner) release( info->index );
+		if ( info->index.is_valid() && info->index_owner ) release( info->index );
 		glDeleteVertexArrays( 1, &info->glid );
-		m_vertex_arrays.destroy( va );
 	}
 }
@@ -113,5 +120,13 @@
 void nv::gl_context::release( framebuffer f )
 {
-	gl_framebuffer_info* info = m_framebuffers.get( f );
+	if ( gl_framebuffer_info* info = m_framebuffers.get( f ) )
+	{
+		release( info );
+		m_framebuffers.destroy( f );
+	}
+}
+
+void nv::gl_context::release( gl_framebuffer_info* info )
+{
 	if ( info )
 	{
@@ -122,5 +137,4 @@
 			glDeleteRenderbuffers( 1, &info->depth_rb_glid );
 		glDeleteFramebuffers( 1, &info->glid );
-		m_framebuffers.destroy( f );
 	}
 }
@@ -881,8 +895,8 @@
 nv::gl_context::~gl_context()
 {
-	while ( m_framebuffers.size() > 0 )
-		release( m_framebuffers.get_handle(0) );
-	while ( m_vertex_arrays.size() > 0 )
-		release( m_vertex_arrays.get_handle(0) );
+	for ( auto& info : m_framebuffers )
+		release( &info );
+	for ( auto& info : m_vertex_arrays )
+		release( &info );
 }
 
Index: /trunk/src/gl/gl_device.cc
===================================================================
--- /trunk/src/gl/gl_device.cc	(revision 542)
+++ /trunk/src/gl/gl_device.cc	(revision 543)
@@ -69,12 +69,12 @@
 gl_device::~gl_device()
 {
-	while ( m_textures.size() > 0 )
-		release( m_textures.get_handle(0) );
-	while ( m_buffers.size() > 0 )
-		release( m_buffers.get_handle(0) );
-	while ( m_programs.size() > 0 )
-		release( m_programs.get_handle(0) );
-	while ( m_shaders.size() > 0 )
-		release( m_shaders.get_handle( 0 ) );
+	for ( auto& t : m_textures )
+		release( &t );
+	for ( auto& b : m_buffers )
+		release( &b );
+	for ( auto& p : m_programs )
+		release( &p );
+	for ( auto& s : m_shaders )
+		release( &s );
 }
 
@@ -131,24 +131,64 @@
 void nv::gl_device::release( texture t )
 {
-	gl_texture_info* info = m_textures.get( t );
-	if ( info )
-	{
-		if ( info->glid != 0 )
-		{
-			glDeleteTextures( 1, &(info->glid) );
-		}
+	if ( auto info = m_textures.get( t ) )
+	{
+		release( info );
 		m_textures.destroy( t );
 	}
 }
 
+void nv::gl_device::release( gl_shader_info* s )
+{
+	if ( s && s->ref == 0 && s->glid != 0 )
+		glDeleteShader( s->glid );
+}
+
+void nv::gl_device::release( gl_program_info* p )
+{
+	if ( p && p->glid != 0 )
+	{
+		for ( auto& i : *p->m_uniform_map )
+			delete i.second;
+
+		gl_shader_info* vi = m_shaders.get( p->vertex );
+		gl_shader_info* fi = m_shaders.get( p->fragment );
+		if ( vi )
+		{
+			glDetachShader( p->glid, vi->glid );
+			vi->ref--;
+			release( vi );
+		}
+		if ( fi )
+		{
+			glDetachShader( p->glid, fi->glid );
+			fi->ref--;
+			release( fi );
+		}
+		glDeleteProgram( p->glid );
+
+		delete p->m_attribute_map;
+		delete p->m_engine_uniforms;
+		delete p->m_uniform_map;
+	}
+
+}
+
+void nv::gl_device::release( gl_texture_info* t )
+{
+	if ( t && t->glid != 0 )
+		glDeleteTextures( 1, &( t->glid ) );
+}
+
+void nv::gl_device::release( gl_buffer_info* b )
+{
+	if ( b && b->glid != 0 )
+		glDeleteBuffers( 1, &( b->glid ) );
+}
+
 void nv::gl_device::release( buffer b )
 {
-	gl_buffer_info* info = m_buffers.get( b );
-	if ( info )
-	{
-		if ( info->glid != 0 )
-		{
-			glDeleteBuffers( 1, &(info->glid) );
-		}
+	if ( auto info = m_buffers.get( b ) )
+	{
+		release( info );
 		m_buffers.destroy( b );
 	}
@@ -204,18 +244,7 @@
 void nv::gl_device::release( program p )
 {
-	gl_program_info* info = m_programs.get( p );
-	if ( info )
-	{
-		for ( auto& i : *info->m_uniform_map )
-			delete i.second;
-
-		detach( p, info->vertex );
-		detach( p, info->fragment );
-		glDeleteProgram( info->glid );
-
-		delete info->m_attribute_map;
-		delete info->m_engine_uniforms;
-		delete info->m_uniform_map;
-
+	if ( auto info = m_programs.get( p ) )
+	{
+		release( info );
 		m_programs.destroy( p );
 	}
@@ -224,8 +253,7 @@
 void nv::gl_device::release( shader s )
 {
-	gl_shader_info* info = m_shaders.get( s );
-	if ( info && info->ref == 0 )
-	{
-		glDeleteShader( info->glid );
+	if ( auto info = m_shaders.get( s ) )
+	{
+		release( info );
 		m_shaders.destroy( s );
 	}
Index: /trunk/src/sdl/sdl_audio.cc
===================================================================
--- /trunk/src/sdl/sdl_audio.cc	(revision 542)
+++ /trunk/src/sdl/sdl_audio.cc	(revision 543)
@@ -111,6 +111,6 @@
 nv::sdl::audio::~audio()
 {
-	while ( m_sounds.size() > 0 )
-		release( m_sounds.get_handle(0) );
+	for ( auto& s : m_sounds )
+		release( &s );
 	Mix_CloseAudio();
 	// TODO: should we do it here?
@@ -121,9 +121,12 @@
 {
 	sound_info* info = m_sounds.get( a_sound );
+	release( info );
+	m_sounds.destroy( a_sound );
+}
+
+void nv::sdl::audio::release( sound_info* info )
+{
 	if ( info )
-	{
 		Mix_FreeChunk( static_cast<Mix_Chunk*>( info->sdl_sound ) );
-		m_sounds.destroy( a_sound );
-	}
 }
 
