Browse Source

Remove the IntrusiveHashMap

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
31eb86e9c1

+ 5 - 7
src/anki/gr/RenderGraph.cpp

@@ -72,11 +72,9 @@ RenderGraph::~RenderGraph()
 	while(!m_renderTargetCache.isEmpty())
 	{
 		auto it = m_renderTargetCache.getBegin();
-		RenderTargetCacheEntry* entry = &*it;
-		m_renderTargetCache.erase(it);
-
-		entry->m_textures.destroy(getAllocator());
-		getAllocator().deleteInstance(entry);
+		RenderTargetCacheEntry& entry = *it;
+		entry.m_textures.destroy(getAllocator());
+		m_renderTargetCache.erase(getAllocator(), it);
 	}
 }
 
@@ -132,8 +130,8 @@ TexturePtr RenderGraph::getOrCreateRenderTarget(const TextureInitInfo& initInf)
 	{
 		// Didn't found the entry, create a new one
 
-		entry = alloc.newInstance<RenderTargetCacheEntry>();
-		m_renderTargetCache.pushBack(initInf, entry);
+		auto it2 = m_renderTargetCache.emplaceBack(getAllocator(), initInf);
+		entry = &(*it2);
 	}
 	else
 	{

+ 2 - 2
src/anki/gr/RenderGraph.h

@@ -337,14 +337,14 @@ private:
 	StackAllocator<U8> m_tmpAlloc;
 
 	/// Render targets of the same type+size+format.
-	class RenderTargetCacheEntry : public IntrusiveHashMapEnabled<RenderTargetCacheEntry>
+	class RenderTargetCacheEntry
 	{
 	public:
 		DynamicArray<TexturePtr> m_textures;
 		U32 m_texturesInUse = 0;
 	};
 
-	IntrusiveHashMap<TextureInitInfo, RenderTargetCacheEntry> m_renderTargetCache; ///< Non-imported render targets.
+	HashMap<TextureInitInfo, RenderTargetCacheEntry> m_renderTargetCache; ///< Non-imported render targets.
 	HashMap<FramebufferInitInfo, FramebufferPtr> m_framebufferCache;
 
 	// Forward declarations

+ 11 - 6
src/anki/gr/vulkan/DescriptorSet.cpp

@@ -15,7 +15,7 @@ namespace anki
 {
 
 /// Descriptor set internal class.
-class DS : public IntrusiveListEnabled<DS>, public IntrusiveHashMapEnabled<DS>
+class DS : public IntrusiveListEnabled<DS>
 {
 public:
 	VkDescriptorSet m_handle = {};
@@ -34,7 +34,7 @@ public:
 	U32 m_lastPoolFreeDSCount = 0;
 
 	IntrusiveList<DS> m_list; ///< At the left of the list are the least used sets.
-	IntrusiveHashMap<U64, DS> m_hashmap;
+	HashMap<U64, DS*> m_hashmap;
 
 	DSThreadAllocator(const DSLayoutCacheEntry* layout, ThreadId tid)
 		: m_layoutEntry(layout)
@@ -116,6 +116,8 @@ DSThreadAllocator::~DSThreadAllocator()
 		vkDestroyDescriptorPool(m_layoutEntry->m_factory->m_dev, pool, nullptr);
 	}
 	m_pools.destroy(alloc);
+
+	m_hashmap.destroy(alloc);
 }
 
 Error DSThreadAllocator::init()
@@ -169,7 +171,7 @@ const DS* DSThreadAllocator::tryFindSet(U64 hash)
 	}
 	else
 	{
-		DS* ds = &(*it);
+		DS* ds = *it;
 
 		// Remove from the list and place at the end of the list
 		m_list.erase(ds);
@@ -196,10 +198,13 @@ Error DSThreadAllocator::newSet(
 		if(frameDiff > DESCRIPTOR_FRAME_BUFFERING)
 		{
 			// Found something, recycle
-			m_hashmap.erase(set);
+			auto it2 = m_hashmap.find(hash);
+			ANKI_ASSERT(it2 != m_hashmap.getEnd());
+			m_hashmap.erase(m_layoutEntry->m_factory->m_alloc, it2);
 			m_list.erase(set);
+
 			m_list.pushBack(set);
-			m_hashmap.pushBack(hash, set);
+			m_hashmap.pushBack(m_layoutEntry->m_factory->m_alloc, hash, set);
 
 			out = set;
 			break;
@@ -234,7 +239,7 @@ Error DSThreadAllocator::newSet(
 		out = m_layoutEntry->m_factory->m_alloc.newInstance<DS>();
 		out->m_handle = handle;
 
-		m_hashmap.pushBack(hash, out);
+		m_hashmap.pushBack(m_layoutEntry->m_factory->m_alloc, hash, out);
 		m_list.pushBack(out);
 	}
 

+ 10 - 16
src/anki/gr/vulkan/PipelineLayout.cpp

@@ -8,21 +8,15 @@
 namespace anki
 {
 
-class PipelineLayoutFactory::Layout : public IntrusiveHashMapEnabled<PipelineLayoutFactory::Layout>
-{
-public:
-	VkPipelineLayout m_handle;
-};
-
 void PipelineLayoutFactory::destroy()
 {
 	while(!m_layouts.isEmpty())
 	{
-		Layout* l = &(*m_layouts.getBegin());
-		m_layouts.erase(l);
+		auto it = m_layouts.getBegin();
+		VkPipelineLayout handle = *it;
+		m_layouts.erase(m_alloc, it);
 
-		vkDestroyPipelineLayout(m_dev, l->m_handle, nullptr);
-		m_alloc.deleteInstance(l);
+		vkDestroyPipelineLayout(m_dev, handle, nullptr);
 	}
 }
 
@@ -49,23 +43,23 @@ Error PipelineLayoutFactory::newPipelineLayout(
 	{
 		// Found it
 
-		layout.m_handle = (*it).m_handle;
+		layout.m_handle = *it;
 	}
 	else
 	{
 		// Not found, create new
 
-		Layout* lay = m_alloc.newInstance<Layout>();
-
 		VkPipelineLayoutCreateInfo ci = {};
 		ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
 		ci.pSetLayouts = &vkDsetLayouts[0];
 		ci.setLayoutCount = dsetLayoutCount;
 
-		ANKI_VK_CHECK(vkCreatePipelineLayout(m_dev, &ci, nullptr, &lay->m_handle));
-		m_layouts.pushBack(hash, lay);
+		VkPipelineLayout pplineLayHandle;
+		ANKI_VK_CHECK(vkCreatePipelineLayout(m_dev, &ci, nullptr, &pplineLayHandle));
+
+		m_layouts.pushBack(m_alloc, hash, pplineLayHandle);
 
-		layout.m_handle = lay->m_handle;
+		layout.m_handle = pplineLayHandle;
 	}
 
 	return Error::NONE;

+ 1 - 3
src/anki/gr/vulkan/PipelineLayout.h

@@ -48,12 +48,10 @@ public:
 	ANKI_USE_RESULT Error newPipelineLayout(const WeakArray<DescriptorSetLayout>& dsetLayouts, PipelineLayout& layout);
 
 private:
-	class Layout;
-
 	GrAllocator<U8> m_alloc;
 	VkDevice m_dev = VK_NULL_HANDLE;
 
-	IntrusiveHashMap<U64, Layout> m_layouts;
+	HashMap<U64, VkPipelineLayout> m_layouts;
 	Mutex m_layoutsMtx;
 };
 /// @}

+ 5 - 4
src/anki/resource/ShaderProgramResource.cpp

@@ -153,8 +153,9 @@ ShaderProgramResource::~ShaderProgramResource()
 
 	while(!m_variants.isEmpty())
 	{
-		ShaderProgramResourceVariant* variant = &(*m_variants.getBegin());
-		m_variants.erase(variant);
+		auto it = m_variants.getBegin();
+		ShaderProgramResourceVariant* variant = *it;
+		m_variants.erase(getAllocator(), it);
 
 		variant->m_blockInfos.destroy(alloc);
 		variant->m_texUnits.destroy(alloc);
@@ -819,7 +820,7 @@ void ShaderProgramResource::getOrCreateVariant(WeakArray<const ShaderProgramReso
 	auto it = m_variants.find(hash);
 	if(it != m_variants.getEnd())
 	{
-		variant = &(*it);
+		variant = *it;
 	}
 	else
 	{
@@ -827,7 +828,7 @@ void ShaderProgramResource::getOrCreateVariant(WeakArray<const ShaderProgramReso
 		ShaderProgramResourceVariant* v = getAllocator().newInstance<ShaderProgramResourceVariant>();
 		initVariant(mutation, constants, *v);
 
-		m_variants.pushBack(hash, v);
+		m_variants.pushBack(getAllocator(), hash, v);
 		variant = v;
 	}
 }

+ 2 - 2
src/anki/resource/ShaderProgramResource.h

@@ -174,7 +174,7 @@ private:
 };
 
 /// Shader program resource variant.
-class ShaderProgramResourceVariant : public IntrusiveHashMapEnabled<ShaderProgramResourceVariant>
+class ShaderProgramResourceVariant
 {
 	friend class ShaderProgramResource;
 
@@ -422,7 +422,7 @@ private:
 
 	Array<String, U(ShaderType::COUNT)> m_sources;
 
-	mutable IntrusiveHashMap<U64, ShaderProgramResourceVariant> m_variants;
+	mutable HashMap<U64, ShaderProgramResourceVariant*> m_variants;
 	mutable Mutex m_mtx;
 
 	Bool8 m_tessellation = false;

+ 0 - 3
src/anki/util/Forward.h

@@ -21,9 +21,6 @@ class BitMask;
 template<typename, typename, typename>
 class HashMap;
 
-template<typename, typename, typename>
-class IntrusiveHashMap;
-
 template<typename T>
 class Hierarchy;
 

+ 6 - 115
src/anki/util/HashMap.h

@@ -56,9 +56,6 @@ class HashMapIterator
 	template<typename, typename, typename>
 	friend class anki::HashMap;
 
-	template<typename, typename, typename>
-	friend class anki::IntrusiveHashMap;
-
 public:
 	/// Default constructor.
 	HashMapIterator()
@@ -307,6 +304,8 @@ private:
 	using Node = detail::HashMapNode<TValue>;
 
 public:
+	using typename Base::Iterator;
+
 	/// Default constructor.
 	HashMap()
 		: Base()
@@ -340,20 +339,22 @@ public:
 
 	/// Copy an element in the map.
 	template<typename TAllocator>
-	void pushBack(TAllocator alloc, const TKey& key, const TValue& x)
+	Iterator pushBack(TAllocator alloc, const TKey& key, const TValue& x)
 	{
 		Node* node = alloc.template newInstance<Node>(x);
 		node->m_hash = THasher()(key);
 		Base::insertNode(node);
+		return Iterator(node);
 	}
 
 	/// Construct an element inside the map.
 	template<typename TAllocator, typename... TArgs>
-	void emplaceBack(TAllocator alloc, const TKey& key, TArgs&&... args)
+	Iterator emplaceBack(TAllocator alloc, const TKey& key, TArgs&&... args)
 	{
 		Node* node = alloc.template newInstance<Node>(std::forward<TArgs>(args)...);
 		node->m_hash = THasher()(key);
 		Base::insertNode(node);
+		return Iterator(node);
 	}
 
 	/// Erase element.
@@ -369,116 +370,6 @@ private:
 	template<typename TAllocator>
 	void destroyInternal(TAllocator alloc, Node* node);
 };
-
-/// The classes that will use the IntrusiveHashMap need to inherit from this one.
-template<typename TClass>
-class IntrusiveHashMapEnabled : public NonCopyable
-{
-	template<typename TKey, typename TValue, typename THasher, typename TNode>
-	friend class detail::HashMapBase;
-
-	template<typename TNodePointer, typename TValuePointer, typename TValueReference>
-	friend class detail::HashMapIterator;
-
-	template<typename TKey, typename TValue, typename THasher>
-	friend class IntrusiveHashMap;
-
-	friend TClass;
-
-public:
-	/// Default constructor.
-	IntrusiveHashMapEnabled() = default;
-
-	/// Move.
-	IntrusiveHashMapEnabled(IntrusiveHashMapEnabled&& b)
-		: m_hash(b.m_hash)
-		, m_left(b.m_left)
-		, m_right(b.m_right)
-		, m_parent(b.m_parent)
-	{
-		b.m_hash = 0;
-		b.m_left = b.m_right = b.m_parent = nullptr;
-	}
-
-	/// Move.
-	IntrusiveHashMapEnabled& operator=(IntrusiveHashMapEnabled&& b)
-	{
-		ANKI_ASSERT(m_hash == 0 && m_left == m_right && m_right == m_parent && m_parent == nullptr);
-		m_hash = b.m_hash;
-		m_left = b.m_left;
-		m_right = b.m_right;
-		m_parent = b.m_parent;
-		b.m_hash = 0;
-		b.m_left = b.m_right = b.m_parent = nullptr;
-		return *this;
-	}
-
-private:
-	U64 m_hash = 0;
-	TClass* m_left = nullptr;
-	TClass* m_right = nullptr;
-	TClass* m_parent = nullptr; ///< Used for iterating.
-
-	TClass& getHashMapNodeValue()
-	{
-		return *static_cast<TClass*>(this);
-	}
-
-	const TClass& getHashMapNodeValue() const
-	{
-		return *static_cast<const TClass*>(this);
-	}
-};
-
-/// Hash map that doesn't perform any allocations. To work the TValue nodes will have to inherit from
-/// IntrusiveHashMapEnabled.
-template<typename TKey, typename TValue, typename THasher = DefaultHasher<TKey>>
-class IntrusiveHashMap : public detail::HashMapBase<TKey, TValue, THasher, TValue>
-{
-private:
-	using Base = detail::HashMapBase<TKey, TValue, THasher, TValue>;
-	using Node = TValue;
-
-public:
-	/// Default constructor.
-	IntrusiveHashMap()
-		: Base()
-	{
-	}
-
-	/// Move.
-	IntrusiveHashMap(IntrusiveHashMap&& b)
-		: Base()
-	{
-		Base::move(b);
-	}
-
-	~IntrusiveHashMap() = default;
-
-	/// Move.
-	IntrusiveHashMap& operator=(IntrusiveHashMap&& b)
-	{
-		Base::move(b);
-		return *this;
-	}
-
-	/// Add an element to the map.
-	void pushBack(const TKey& key, TValue* x)
-	{
-		ANKI_ASSERT(x);
-		IntrusiveHashMapEnabled<TValue>* e = static_cast<IntrusiveHashMapEnabled<TValue>*>(x);
-		e->m_hash = THasher()(key);
-		e->m_left = e->m_right = e->m_parent = nullptr;
-		Base::insertNode(x);
-	}
-
-	/// Erase element.
-	void erase(typename Base::Iterator it)
-	{
-		Node* del = it.m_node;
-		Base::removeNode(del);
-	}
-};
 /// @}
 
 } // end namespace anki

+ 1 - 38
tests/util/HashMap.cpp

@@ -257,41 +257,4 @@ ANKI_TEST(Util, HashMap)
 
 		akMap.destroy(alloc);
 	}
-}
-
-class Hashable : public IntrusiveHashMapEnabled<Hashable>
-{
-public:
-	Hashable(int x)
-		: m_x(x)
-	{
-	}
-
-	int m_x;
-};
-
-ANKI_TEST(Util, IntrusiveHashMap)
-{
-	Hashable a(1);
-	Hashable b(2);
-	Hashable c(10);
-
-	IntrusiveHashMap<int, Hashable, Hasher> map;
-
-	// Add vals
-	map.pushBack(1, &a);
-	map.pushBack(2, &b);
-	map.pushBack(10, &c);
-
-	// Find
-	ANKI_TEST_EXPECT_EQ(map.find(1)->m_x, 1);
-	ANKI_TEST_EXPECT_EQ(map.find(10)->m_x, 10);
-
-	// Erase
-	map.erase(map.find(10));
-	ANKI_TEST_EXPECT_EQ(map.find(10), map.getEnd());
-
-	// Put back
-	map.pushBack(10, &c);
-	ANKI_TEST_EXPECT_NEQ(map.find(10), map.getEnd());
-}
+}