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.
5 // This file contains the definition of the FencedAllocator class.
7 #ifndef GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
8 #define GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
12 #include "gpu/command_buffer/common/logging.h"
13 #include "gpu/command_buffer/common/types.h"
14 #include "gpu/gpu_export.h"
17 class CommandBufferHelper
;
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
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
{
31 typedef unsigned int Offset
;
32 // Invalid offset, returned by Alloc in case of failure.
33 static const Offset kInvalidOffset
= 0xffffffffU
;
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
);
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.
47 // size: the size of the memory block to allocate.
50 // the offset of the allocated memory block, or kInvalidOffset if out of
52 Offset
Alloc(unsigned int size
);
54 // Frees a block of memory.
57 // offset: the offset of the memory block to free.
58 void Free(Offset offset
);
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.
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
);
68 // Frees any blocks pending a token for which the token has been read.
71 // Gets the size of the largest free block that is available without waiting.
72 unsigned int GetLargestFreeSize();
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
77 unsigned int GetLargestFreeOrPendingSize();
79 // Checks for consistency inside the book-keeping structures. Used for
81 bool CheckConsistency();
83 // True if any memory is allocated.
86 // Return bytes of memory that is IN_USE
87 size_t bytes_in_use() const { return bytes_in_use_
; }
90 // Status of a block of memory, for book-keeping.
97 // Book-keeping sturcture that describes a block of memory.
102 int32 token
; // token to wait for in the FREE_PENDING_TOKEN case.
105 // Comparison functor for memory block sorting.
108 bool operator() (const Block
&left
, const Block
&right
) {
109 return left
.offset
< right
.offset
;
113 typedef std::vector
<Block
> Container
;
114 typedef unsigned int BlockIndex
;
116 static const int32 kUnusedToken
= 0;
118 // Gets the index of a memory block, given its offset.
119 BlockIndex
GetBlockByOffset(Offset offset
);
121 // Collapse a free block with its neighbours if they are free. Returns the
122 // index of the collapsed block.
123 // NOTE: this will invalidate block indices.
124 BlockIndex
CollapseFreeBlock(BlockIndex index
);
126 // Waits for a FREE_PENDING_TOKEN block to be usable, and free it. Returns
127 // the new index of that block (since it may have been collapsed).
128 // NOTE: this will invalidate block indices.
129 BlockIndex
WaitForTokenAndFreeBlock(BlockIndex index
);
131 // Allocates a block of memory inside a given block, splitting it in two
132 // (unless that block is of the exact requested size).
133 // NOTE: this will invalidate block indices.
134 // Returns the offset of the allocated block (NOTE: this is different from
135 // the other functions that return a block index).
136 Offset
AllocInBlock(BlockIndex index
, unsigned int size
);
138 CommandBufferHelper
*helper_
;
140 size_t bytes_in_use_
;
142 DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocator
);
145 // This class functions just like FencedAllocator, but its API uses pointers
146 // instead of offsets.
147 class FencedAllocatorWrapper
{
149 FencedAllocatorWrapper(unsigned int size
,
150 CommandBufferHelper
* helper
,
152 : allocator_(size
, helper
),
155 // Allocates a block of memory. If the buffer is out of directly available
156 // memory, this function may wait until memory that was freed "pending a
157 // token" can be re-used.
160 // size: the size of the memory block to allocate.
163 // the pointer to the allocated memory block, or NULL if out of
165 void *Alloc(unsigned int size
) {
166 FencedAllocator::Offset offset
= allocator_
.Alloc(size
);
167 return GetPointer(offset
);
170 // Allocates a block of memory. If the buffer is out of directly available
171 // memory, this function may wait until memory that was freed "pending a
172 // token" can be re-used.
173 // This is a type-safe version of Alloc, returning a typed pointer.
176 // count: the number of elements to allocate.
179 // the pointer to the allocated memory block, or NULL if out of
181 template <typename T
> T
*AllocTyped(unsigned int count
) {
182 return static_cast<T
*>(Alloc(count
* sizeof(T
)));
185 // Frees a block of memory.
188 // pointer: the pointer to the memory block to free.
189 void Free(void *pointer
) {
191 allocator_
.Free(GetOffset(pointer
));
194 // Frees a block of memory, pending the passage of a token. That memory won't
195 // be re-allocated until the token has passed through the command stream.
198 // pointer: the pointer to the memory block to free.
199 // token: the token value to wait for before re-using the memory.
200 void FreePendingToken(void *pointer
, int32 token
) {
202 allocator_
.FreePendingToken(GetOffset(pointer
), token
);
205 // Frees any blocks pending a token for which the token has been read.
207 allocator_
.FreeUnused();
210 // Gets a pointer to a memory block given the base memory and the offset.
211 // It translates FencedAllocator::kInvalidOffset to NULL.
212 void *GetPointer(FencedAllocator::Offset offset
) {
213 return (offset
== FencedAllocator::kInvalidOffset
) ?
214 NULL
: static_cast<char *>(base_
) + offset
;
217 // Gets the offset to a memory block given the base memory and the address.
218 // It translates NULL to FencedAllocator::kInvalidOffset.
219 FencedAllocator::Offset
GetOffset(void *pointer
) {
221 static_cast<FencedAllocator::Offset
>(
222 static_cast<char*>(pointer
) - static_cast<char*>(base_
)) :
223 FencedAllocator::kInvalidOffset
;
226 // Gets the size of the largest free block that is available without waiting.
227 unsigned int GetLargestFreeSize() {
228 return allocator_
.GetLargestFreeSize();
231 // Gets the size of the largest free block that can be allocated if the
233 unsigned int GetLargestFreeOrPendingSize() {
234 return allocator_
.GetLargestFreeOrPendingSize();
237 // Checks for consistency inside the book-keeping structures. Used for
239 bool CheckConsistency() {
240 return allocator_
.CheckConsistency();
243 // True if any memory is allocated.
245 return allocator_
.InUse();
248 FencedAllocator
&allocator() { return allocator_
; }
250 size_t bytes_in_use() const { return allocator_
.bytes_in_use(); }
253 FencedAllocator allocator_
;
255 DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocatorWrapper
);
260 #endif // GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_