1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // This file contains the definition of the FencedAllocator class. 6 7 #ifndef GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_ 8 #define GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_ 9 10 #include <vector> 11 12 #include "gpu/command_buffer/common/logging.h" 13 #include "gpu/command_buffer/common/types.h" 14 #include "gpu/gpu_export.h" 15 16 namespace gpu { 17 class CommandBufferHelper; 18 19 // FencedAllocator provides a mechanism to manage allocations within a fixed 20 // block of memory (storing the book-keeping externally). Furthermore this 21 // class allows to free data "pending" the passage of a command buffer token, 22 // that is, the memory won't be reused until the command buffer has processed 23 // that token. 24 // 25 // NOTE: Although this class is intended to be used in the command buffer 26 // environment which is multi-process, this class isn't "thread safe", because 27 // it isn't meant to be shared across modules. It is thread-compatible though 28 // (see http://www.corp.google.com/eng/doc/cpp_primer.html#thread_safety). 29 class GPU_EXPORT FencedAllocator { 30 public: 31 typedef unsigned int Offset; 32 // Invalid offset, returned by Alloc in case of failure. 33 static const Offset kInvalidOffset = 0xffffffffU; 34 35 // Creates a FencedAllocator. Note that the size of the buffer is passed, but 36 // not its base address: everything is handled as offsets into the buffer. 37 FencedAllocator(unsigned int size, 38 CommandBufferHelper *helper); 39 40 ~FencedAllocator(); 41 42 // Allocates a block of memory. If the buffer is out of directly available 43 // memory, this function may wait until memory that was freed "pending a 44 // token" can be re-used. 45 // 46 // Parameters: 47 // size: the size of the memory block to allocate. 48 // 49 // Returns: 50 // the offset of the allocated memory block, or kInvalidOffset if out of 51 // memory. 52 Offset Alloc(unsigned int size); 53 54 // Frees a block of memory. 55 // 56 // Parameters: 57 // offset: the offset of the memory block to free. 58 void Free(Offset offset); 59 60 // Frees a block of memory, pending the passage of a token. That memory won't 61 // be re-allocated until the token has passed through the command stream. 62 // 63 // Parameters: 64 // offset: the offset of the memory block to free. 65 // token: the token value to wait for before re-using the memory. 66 void FreePendingToken(Offset offset, int32 token); 67 68 // Frees any blocks pending a token for which the token has been read. 69 void FreeUnused(); 70 71 // Gets the size of the largest free block that is available without waiting. 72 unsigned int GetLargestFreeSize(); 73 74 // Gets the size of the largest free block that can be allocated if the 75 // caller can wait. Allocating a block of this size will succeed, but may 76 // block. 77 unsigned int GetLargestFreeOrPendingSize(); 78 79 // Checks for consistency inside the book-keeping structures. Used for 80 // testing. 81 bool CheckConsistency(); 82 83 // True if any memory is allocated. 84 bool InUse(); 85 86 private: 87 // Status of a block of memory, for book-keeping. 88 enum State { 89 IN_USE, 90 FREE, 91 FREE_PENDING_TOKEN 92 }; 93 94 // Book-keeping sturcture that describes a block of memory. 95 struct Block { 96 State state; 97 Offset offset; 98 unsigned int size; 99 int32 token; // token to wait for in the FREE_PENDING_TOKEN case. 100 }; 101 102 // Comparison functor for memory block sorting. 103 class OffsetCmp { 104 public: 105 bool operator() (const Block &left, const Block &right) { 106 return left.offset < right.offset; 107 } 108 }; 109 110 typedef std::vector<Block> Container; 111 typedef unsigned int BlockIndex; 112 113 static const int32 kUnusedToken = 0; 114 115 // Gets the index of a memory block, given its offset. 116 BlockIndex GetBlockByOffset(Offset offset); 117 118 // Collapse a free block with its neighbours if they are free. Returns the 119 // index of the collapsed block. 120 // NOTE: this will invalidate block indices. 121 BlockIndex CollapseFreeBlock(BlockIndex index); 122 123 // Waits for a FREE_PENDING_TOKEN block to be usable, and free it. Returns 124 // the new index of that block (since it may have been collapsed). 125 // NOTE: this will invalidate block indices. 126 BlockIndex WaitForTokenAndFreeBlock(BlockIndex index); 127 128 // Allocates a block of memory inside a given block, splitting it in two 129 // (unless that block is of the exact requested size). 130 // NOTE: this will invalidate block indices. 131 // Returns the offset of the allocated block (NOTE: this is different from 132 // the other functions that return a block index). 133 Offset AllocInBlock(BlockIndex index, unsigned int size); 134 135 CommandBufferHelper *helper_; 136 Container blocks_; 137 138 DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocator); 139 }; 140 141 // This class functions just like FencedAllocator, but its API uses pointers 142 // instead of offsets. 143 class FencedAllocatorWrapper { 144 public: 145 FencedAllocatorWrapper(unsigned int size, 146 CommandBufferHelper* helper, 147 void* base) 148 : allocator_(size, helper), 149 base_(base) { } 150 151 // Allocates a block of memory. If the buffer is out of directly available 152 // memory, this function may wait until memory that was freed "pending a 153 // token" can be re-used. 154 // 155 // Parameters: 156 // size: the size of the memory block to allocate. 157 // 158 // Returns: 159 // the pointer to the allocated memory block, or NULL if out of 160 // memory. 161 void *Alloc(unsigned int size) { 162 FencedAllocator::Offset offset = allocator_.Alloc(size); 163 return GetPointer(offset); 164 } 165 166 // Allocates a block of memory. If the buffer is out of directly available 167 // memory, this function may wait until memory that was freed "pending a 168 // token" can be re-used. 169 // This is a type-safe version of Alloc, returning a typed pointer. 170 // 171 // Parameters: 172 // count: the number of elements to allocate. 173 // 174 // Returns: 175 // the pointer to the allocated memory block, or NULL if out of 176 // memory. 177 template <typename T> T *AllocTyped(unsigned int count) { 178 return static_cast<T *>(Alloc(count * sizeof(T))); 179 } 180 181 // Frees a block of memory. 182 // 183 // Parameters: 184 // pointer: the pointer to the memory block to free. 185 void Free(void *pointer) { 186 GPU_DCHECK(pointer); 187 allocator_.Free(GetOffset(pointer)); 188 } 189 190 // Frees a block of memory, pending the passage of a token. That memory won't 191 // be re-allocated until the token has passed through the command stream. 192 // 193 // Parameters: 194 // pointer: the pointer to the memory block to free. 195 // token: the token value to wait for before re-using the memory. 196 void FreePendingToken(void *pointer, int32 token) { 197 GPU_DCHECK(pointer); 198 allocator_.FreePendingToken(GetOffset(pointer), token); 199 } 200 201 // Frees any blocks pending a token for which the token has been read. 202 void FreeUnused() { 203 allocator_.FreeUnused(); 204 } 205 206 // Gets a pointer to a memory block given the base memory and the offset. 207 // It translates FencedAllocator::kInvalidOffset to NULL. 208 void *GetPointer(FencedAllocator::Offset offset) { 209 return (offset == FencedAllocator::kInvalidOffset) ? 210 NULL : static_cast<char *>(base_) + offset; 211 } 212 213 // Gets the offset to a memory block given the base memory and the address. 214 // It translates NULL to FencedAllocator::kInvalidOffset. 215 FencedAllocator::Offset GetOffset(void *pointer) { 216 return pointer ? 217 static_cast<FencedAllocator::Offset>( 218 static_cast<char*>(pointer) - static_cast<char*>(base_)) : 219 FencedAllocator::kInvalidOffset; 220 } 221 222 // Gets the size of the largest free block that is available without waiting. 223 unsigned int GetLargestFreeSize() { 224 return allocator_.GetLargestFreeSize(); 225 } 226 227 // Gets the size of the largest free block that can be allocated if the 228 // caller can wait. 229 unsigned int GetLargestFreeOrPendingSize() { 230 return allocator_.GetLargestFreeOrPendingSize(); 231 } 232 233 // Checks for consistency inside the book-keeping structures. Used for 234 // testing. 235 bool CheckConsistency() { 236 return allocator_.CheckConsistency(); 237 } 238 239 // True if any memory is allocated. 240 bool InUse() { 241 return allocator_.InUse(); 242 } 243 244 FencedAllocator &allocator() { return allocator_; } 245 246 private: 247 FencedAllocator allocator_; 248 void* base_; 249 DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocatorWrapper); 250 }; 251 252 } // namespace gpu 253 254 #endif // GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_ 255