From bcf029f3330db5ad7e3994cf519df7c43476b418 Mon Sep 17 00:00:00 2001 From: "ted.mielczarek@gmail.com" Date: Fri, 17 May 2013 19:47:10 +0000 Subject: [PATCH] Use std::vector with a custom allocator wrapping PageAllocator for wasteful_vector Patch by Mike Hommey , R=me at https://breakpad.appspot.com/581002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1184 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/common/memory.h | 111 ++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 76 deletions(-) diff --git a/src/common/memory.h b/src/common/memory.h index 1fda60f9..cb37b5fa 100644 --- a/src/common/memory.h +++ b/src/common/memory.h @@ -30,13 +30,13 @@ #ifndef GOOGLE_BREAKPAD_COMMON_MEMORY_H_ #define GOOGLE_BREAKPAD_COMMON_MEMORY_H_ +#include +#include #include #include #include #include -#include - #ifdef __APPLE__ #define sys_mmap mmap #define sys_mmap2 mmap @@ -133,83 +133,42 @@ class PageAllocator { unsigned page_offset_; }; -// A wasteful vector is like a normal std::vector, except that it's very much -// simplier and it allocates memory from a PageAllocator. It's wasteful -// because, when resizing, it always allocates a whole new array since the -// PageAllocator doesn't support realloc. +// Wrapper to use with STL containers +template +struct PageStdAllocator: public std::allocator { + typedef typename std::allocator::pointer pointer; + typedef typename std::allocator::size_type size_type; + + PageStdAllocator(PageAllocator& allocator): allocator_(allocator) {} + template PageStdAllocator(const PageStdAllocator& other): + allocator_(other.allocator_) {} + + inline pointer allocator(size_type n, const void* = 0) { + return allocator_.Alloc(sizeof(T) * n); + } + + inline void deallocate(pointer, size_type) { + // The PageAllocator doesn't free. + } + + template struct rebind { + typedef PageStdAllocator other; + }; + +private: + PageAllocator& allocator_; +}; + +// A wasteful vector is a std::vector, except that it allocates memory from a +// PageAllocator. It's wasteful because, when resizing, it always allocates a +// whole new array since the PageAllocator doesn't support realloc. template -class wasteful_vector { +class wasteful_vector: public std::vector > { public: - wasteful_vector(PageAllocator *allocator, unsigned size_hint = 16) - : allocator_(allocator), - a_((T*) allocator->Alloc(sizeof(T) * size_hint)), - allocated_(size_hint), - used_(0) { + wasteful_vector(PageAllocator* allocator, unsigned size_hint = 16) + : std::vector >(PageStdAllocator(*allocator)) { + std::vector >::reserve(size_hint); } - - T& back() { - return a_[used_ - 1]; - } - - const T& back() const { - return a_[used_ - 1]; - } - - bool empty() const { - return used_ == 0; - } - - void push_back(const T& new_element) { - if (used_ == allocated_) - Realloc(std::max(allocated_ * 2, 1u)); - a_[used_++] = new_element; - } - - size_t size() const { - return used_; - } - - void resize(unsigned sz, T c = T()) { - // No need to test "sz >= 0", as "sz" is unsigned. - if (sz <= used_) { - used_ = sz; - } else { - unsigned a = allocated_; - if (sz > a) { - while (sz > a) { - a *= 2; - } - Realloc(a); - } - while (sz > used_) { - a_[used_++] = c; - } - } - } - - T& operator[](size_t index) { - return a_[index]; - } - - const T& operator[](size_t index) const { - return a_[index]; - } - - private: - void Realloc(unsigned new_size) { - T *new_array = - reinterpret_cast(allocator_->Alloc(sizeof(T) * new_size)); - if (new_size > 0) { - memcpy(new_array, a_, used_ * sizeof(T)); - } - a_ = new_array; - allocated_ = new_size; - } - - PageAllocator *const allocator_; - T *a_; // pointer to an array of |allocated_| elements. - unsigned allocated_; // size of |a_|, in elements. - unsigned used_; // number of used slots in |a_|. }; } // namespace google_breakpad