15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef COURGETTE_MEMORY_ALLOCATOR_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define COURGETTE_MEMORY_ALLOCATOR_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <memory> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A helper class to track down call sites that are not handling error cases. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CheckReturnValue { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not marked explicit on purpose. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckReturnValue(T value) : value_(value), checked_(false) { // NOLINT 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckReturnValue(const CheckReturnValue& other) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : value_(other.value_), checked_(other.checked_) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other.checked_ = true; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckReturnValue& operator=(const CheckReturnValue& other) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this != &other) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(checked_); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_ = other.value_; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checked_ = other.checked_; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other.checked_ = true; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~CheckReturnValue() { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(checked_); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operator const T&() const { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checked_ = true; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value_; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T value_; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable bool checked_; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef CheckReturnValue<bool> CheckBool; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef bool CheckBool; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace courgette { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Manages a read/write virtual mapping of a physical file. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FileMapping { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileMapping(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~FileMapping(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Map a file from beginning to |size|. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Create(HANDLE file, size_t size); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Close(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true iff a mapping has been created. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool valid() const; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns a writable pointer to the beginning of the memory mapped file. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If Create has not been called successfully, return value is NULL. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* view() const; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool InitializeView(size_t size); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE mapping_; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* view_; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Manages a temporary file and a memory mapping of the temporary file. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The memory that this class manages holds a pointer back to the TempMapping 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object itself, so that given a memory pointer allocated by this class, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// you can get a pointer to the TempMapping instance that owns that memory. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TempMapping { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempMapping(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~TempMapping(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a temporary file of size |size| and maps it into the current 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process's address space. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Initialize(size_t size); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns a writable pointer to the reserved memory. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* memory() const; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the mapping is valid and memory is available. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool valid() const; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns a pointer to the TempMapping instance that allocated the |mem| 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // block of memory. It's the callers responsibility to make sure that 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the memory block was allocated by the TempMapping class. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static TempMapping* GetMappingFromPtr(void* mem); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File file_; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileMapping mapping_; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A memory allocator class that allocates memory either from the heap or via a 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temporary file. The interface is STL inspired but the class does not throw 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// STL exceptions on allocation failure. Instead it returns NULL. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A file allocation will be made if either the requested memory size exceeds 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |kMaxHeapAllocationSize| or if a heap allocation fails. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Allocating the memory as a mapping of a temporary file solves the problem 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that there might not be enough physical memory and pagefile to support the 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocation. This can happen because these resources are too small, or 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// already committed to other processes. Provided there is enough disk, the 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temporary file acts like a pagefile that other processes can't access. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T> 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MemoryAllocator { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef T value_type; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef value_type* pointer; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef value_type& reference; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const value_type* const_pointer; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const value_type& const_reference; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef size_t size_type; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef ptrdiff_t difference_type; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Each allocation is tagged with a single byte so that we know how to 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deallocate it. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum AllocationType { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAP_ALLOCATION, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_ALLOCATION, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5MB is the maximum heap allocation size that we'll attempt. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When applying a patch for Chrome 10.X we found that at this 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threshold there were 17 allocations higher than this threshold 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (largest at 136MB) 10 allocations just below the threshold and 6362 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // smaller allocations. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kMaxHeapAllocationSize = 1024 * 1024 * 5; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<class OtherT> 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct rebind { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // convert a MemoryAllocator<T> to a MemoryAllocator<OtherT> 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MemoryAllocator<OtherT> other; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryAllocator() _THROW0() { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't use an explicit constructor here, as dictated by our style guide. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The implementation of basic_string in Visual Studio 2010 prevents this. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryAllocator(const MemoryAllocator<T>& other) _THROW0() { // NOLINT 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<class OtherT> 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryAllocator(const MemoryAllocator<OtherT>& other) _THROW0() { // NOLINT 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~MemoryAllocator() { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void deallocate(pointer ptr, size_type size) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* mem = reinterpret_cast<uint8*>(ptr); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mem -= sizeof(T); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mem[0] == HEAP_ALLOCATION) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] mem; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(static_cast<uint8>(FILE_ALLOCATION), mem[0]); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempMapping* mapping = TempMapping::GetMappingFromPtr(mem); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete mapping; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer allocate(size_type count) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use the first byte of each allocation to mark the allocation type. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // However, so that the allocation is properly aligned, we allocate an 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extra element and then use the first byte of the first element 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to mark the allocation type. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count++; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count > max_size()) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_type bytes = count * sizeof(T); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* mem = NULL; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First see if we can do this allocation on the heap. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count < kMaxHeapAllocationSize) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mem = new(std::nothrow) uint8[bytes]; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mem != NULL) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mem[0] = static_cast<uint8>(HEAP_ALLOCATION); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If either the heap allocation failed or the request exceeds the 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // max heap allocation threshold, we back the allocation with a temp file. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempMapping* mapping = new(std::nothrow) TempMapping(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mapping && mapping->Initialize(bytes)) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mem = reinterpret_cast<uint8*>(mapping->memory()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mem[0] = static_cast<uint8>(FILE_ALLOCATION); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mem ? reinterpret_cast<pointer>(mem + sizeof(T)) : NULL; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer allocate(size_type count, const void* hint) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return allocate(count); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void construct(pointer ptr, const T& value) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::new(ptr) T(value); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void destroy(pointer ptr) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr->~T(); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_type max_size() const _THROW0() { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_type count = static_cast<size_type>(-1) / sizeof(T); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0 < count ? count : 1); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // OS_WIN 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Mac, Linux, we use a bare bones implementation that only does 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heap allocations. 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T> 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MemoryAllocator { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef T value_type; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef value_type* pointer; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef value_type& reference; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const value_type* const_pointer; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef const value_type& const_reference; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef size_t size_type; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef ptrdiff_t difference_type; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<class OtherT> 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct rebind { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // convert a MemoryAllocator<T> to a MemoryAllocator<OtherT> 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef MemoryAllocator<OtherT> other; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryAllocator() { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit MemoryAllocator(const MemoryAllocator<T>& other) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<class OtherT> 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit MemoryAllocator(const MemoryAllocator<OtherT>& other) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~MemoryAllocator() { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void deallocate(pointer ptr, size_type size) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] ptr; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer allocate(size_type count) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count > max_size()) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<pointer>( 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new(std::nothrow) uint8[count * sizeof(T)]); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer allocate(size_type count, const void* hint) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return allocate(count); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void construct(pointer ptr, const T& value) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::new(ptr) T(value); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void destroy(pointer ptr) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr->~T(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_type max_size() const { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_type count = static_cast<size_type>(-1) / sizeof(T); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0 < count ? count : 1); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_WIN 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Manages a growable buffer. The buffer allocation is done by the 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MemoryAllocator class. This class will not throw exceptions so call sites 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// must be prepared to handle memory allocation failures. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The interface is STL inspired to avoid having to make too many changes 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to code that previously was using STL. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T, class Allocator = MemoryAllocator<T> > 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NoThrowBuffer { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef T value_type; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kAllocationFailure = 0xffffffff; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kStartSize = sizeof(T) > 0x100 ? 1 : 0x100 / sizeof(T); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NoThrowBuffer() : buffer_(NULL), size_(0), alloc_size_(0) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~NoThrowBuffer() { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clear(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void clear() { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alloc_.deallocate(buffer_, alloc_size_); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_ = NULL; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = 0; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alloc_size_ = 0; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool empty() const { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_ == 0; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckBool reserve(size_t size) WARN_UNUSED_RESULT { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (failed()) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size <= alloc_size_) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size < kStartSize) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = kStartSize; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Use a size 1% higher than requested. In practice, this makes Courgette as 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // much as 5x faster on typical Chrome update payloads as a lot of future 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // reserve() calls will become no-ops instead of costly resizes that copy 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // all the data. Note that doing this here instead of outside the function 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // is more efficient, since it's after the no-op early return checks above. 3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size *= 1.01; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* new_buffer = alloc_.allocate(size); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_buffer) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clear(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alloc_size_ = kAllocationFailure; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_) { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(new_buffer, buffer_, size_ * sizeof(T)); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alloc_.deallocate(buffer_, alloc_size_); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_ = new_buffer; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alloc_size_ = size; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !failed(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckBool append(const T* data, size_t size) WARN_UNUSED_RESULT { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (failed()) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > alloc_.max_size() - size_) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((alloc_size_ - size_) < size) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t max_size = alloc_.max_size(); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t new_size = alloc_size_ ? alloc_size_ : kStartSize; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (new_size < size_ + size) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_size < max_size - new_size) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_size *= 2; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_size = max_size; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!reserve(new_size)) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buffer_ + size_, data, size * sizeof(T)); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ += size; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckBool resize(size_t size, const T& init_value) WARN_UNUSED_RESULT { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > size_) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!reserve(size)) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = size_; i < size; ++i) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_[i] = init_value; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (size < size_) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(tommi): Should we allocate a new, smaller buffer? 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It might be faster for us to simply change the size. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = size; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckBool push_back(const T& item) WARN_UNUSED_RESULT { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return append(&item, 1); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T& back() const { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer_[size_ - 1]; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T& back() { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer_[size_ - 1]; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T* begin() const { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size_) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &buffer_[0]; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* begin() { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size_) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &buffer_[0]; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T* end() const { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size_) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &buffer_[size_ - 1]; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* end() { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size_) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &buffer_[size_ - 1]; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T& operator[](size_t index) const { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index < size_); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer_[index]; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T& operator[](size_t index) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index < size_); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer_[index]; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size() const { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* data() const { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer_; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if an allocation failure has ever occurred for this object. 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool failed() const { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return alloc_size_ == kAllocationFailure; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* buffer_; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size_; // how much of the buffer we're using. 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t alloc_size_; // how much space we have allocated. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator alloc_; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace courgette 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // COURGETTE_MEMORY_ALLOCATOR_H_ 473