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