diff options
| author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-05-02 15:40:30 -0700 | 
|---|---|---|
| committer | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-05-02 15:40:30 -0700 | 
| commit | fa8663c066e98170dd385bff7bc33e7cfeabfcc4 (patch) | |
| tree | c38a3a0db5ff54c41cc7f6a46fb41756be77419a | |
| parent | 613301ce5143f0ce5f00f914d27d309b2e2efd75 (diff) | |
Revise marker deletion strategy
Instead of checking if the object being removed allocated a marker, mark the
marker block as deleted immediately upon allocation. This simplifies the logic
and prevents extra markers from being inserted if we allocate/deallocate the
same node indefinitely.
Also change marker pointer type to uint32_t*.
| -rw-r--r-- | src/pugixml.cpp | 51 | 
1 files changed, 22 insertions, 29 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index c98ee40..033bf13 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -473,7 +473,7 @@ PUGI__NS_BEGIN  	#ifdef PUGIXML_COMPACT  		char_t* compact_string_base;  		void* compact_shared_parent; -		char* compact_page_marker; +		uint32_t* compact_page_marker;  	#endif  	}; @@ -556,7 +556,16 @@ PUGI__NS_BEGIN  					assert(_root == page);  					// top page freed, just reset sizes -					page->busy_size = page->freed_size = 0; +					page->busy_size = 0; +					page->freed_size = 0; + +				#ifdef PUGIXML_COMPACT +					// reset compact state to maximize efficiency +					page->compact_string_base = 0; +					page->compact_shared_parent = 0; +					page->compact_page_marker = 0; +				#endif +  					_busy_size = 0;  				}  				else @@ -696,7 +705,7 @@ PUGI__NS_BEGIN  			PUGI__STATIC_ASSERT(xml_memory_block_alignment == compact_alignment);  			PUGI__STATIC_ASSERT(sizeof(xml_memory_page) + xml_memory_page_size <= (1 << (16 + compact_alignment_log2))); -			ptrdiff_t offset = (reinterpret_cast<char*>(this) - page->compact_page_marker); +			ptrdiff_t offset = (reinterpret_cast<char*>(this) - reinterpret_cast<char*>(page->compact_page_marker));  			assert(offset >= 0 && offset < 256 << compact_alignment_log2);  			_page = static_cast<unsigned char>(offset >> compact_alignment_log2); @@ -725,11 +734,6 @@ PUGI__NS_BEGIN  			return const_cast<xml_memory_page*>(reinterpret_cast<const xml_memory_page*>(page_marker - *reinterpret_cast<const uint32_t*>(page_marker)));  		} -		bool has_marker() const -		{ -			return _page == sizeof(uint32_t) >> compact_alignment_log2; -		} -  	private:  		unsigned char _page;  		unsigned char _flags; @@ -1122,13 +1126,17 @@ PUGI__NS_BEGIN  		if (!result) return 0;  		// adjust for marker -		if (PUGI__UNLIKELY(static_cast<uintptr_t>(static_cast<char*>(result) - out_page->compact_page_marker) >= 256 * compact_alignment)) +		if (PUGI__UNLIKELY(static_cast<uintptr_t>(static_cast<char*>(result) - reinterpret_cast<char*>(out_page->compact_page_marker)) >= 256 * compact_alignment))  		{  			// insert new marker  			uint32_t* marker = static_cast<uint32_t*>(result);  			*marker = reinterpret_cast<char*>(marker) - reinterpret_cast<char*>(out_page); -			out_page->compact_page_marker = reinterpret_cast<char*>(marker); +			out_page->compact_page_marker = marker; + +			// since we don't reuse the page space until we reallocate it, we can just pretend that we freed the marker block +			// this will make sure deallocate_memory correctly tracks the size +			out_page->freed_size += sizeof(uint32_t);  			return marker + 1;  		} @@ -1140,26 +1148,11 @@ PUGI__NS_BEGIN  			return result;  		}  	} - -	template <typename T> -	inline void deallocate_object(xml_allocator& alloc, T* ptr, size_t size, xml_memory_page* page) -	{ -		// this is very crude... we should be able to do better? -		if (ptr->header.has_marker()) -			page->compact_page_marker = 0; - -		alloc.deallocate_memory(ptr, size + ptr->header.has_marker() * sizeof(uint32_t), page); -	}  #else  	inline void* allocate_object(xml_allocator& alloc, size_t size, xml_memory_page*& out_page)  	{  		return alloc.allocate_memory(size, out_page);  	} - -	inline void deallocate_object(xml_allocator& alloc, void* ptr, size_t size, xml_memory_page* page) -	{ -		alloc.deallocate_memory(ptr, size, page); -	}  #endif  	inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) @@ -1186,7 +1179,7 @@ PUGI__NS_BEGIN  		if (a->header & impl::xml_memory_page_value_allocated_mask)  			alloc.deallocate_string(a->value); -		deallocate_object(alloc, a, sizeof(xml_attribute_struct), PUGI__GETPAGE(a)); +		alloc.deallocate_memory(a, sizeof(xml_attribute_struct), PUGI__GETPAGE(a));  	}  	inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) @@ -1215,7 +1208,7 @@ PUGI__NS_BEGIN  			child = next;  		} -		deallocate_object(alloc, n, sizeof(xml_node_struct), PUGI__GETPAGE(n)); +		alloc.deallocate_memory(n, sizeof(xml_node_struct), PUGI__GETPAGE(n));  	}  	inline void append_node(xml_node_struct* child, xml_node_struct* node) @@ -6725,8 +6718,8 @@ namespace pugi  		// setup first page marker  	#ifdef PUGIXML_COMPACT -		page->compact_page_marker = reinterpret_cast<char*>(page) + sizeof(impl::xml_memory_page); -		*reinterpret_cast<uint32_t*>(page->compact_page_marker) = sizeof(impl::xml_memory_page); +		page->compact_page_marker = reinterpret_cast<uint32_t*>(reinterpret_cast<char*>(page) + sizeof(impl::xml_memory_page)); +		*page->compact_page_marker = sizeof(impl::xml_memory_page);  	#endif  		// allocate new root  | 
