blob: be8b1d78e92121112e52f0003c19fbd6d5e43514 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#ifndef GrMemory_DEFINED
19#define GrMemory_DEFINED
20
21#include "GrNoncopyable.h"
22
23class GrAutoMalloc : GrNoncopyable {
24public:
bsalomon@google.com1c13c962011-02-14 16:51:21 +000025 GrAutoMalloc() : fPtr(NULL), fAllocatedBytes(0){
26 }
27
28 GrAutoMalloc(size_t bytes) : fPtr(GrMalloc(bytes)), fAllocatedBytes(bytes) {}
reed@google.comac10a2d2010-12-22 21:39:39 +000029 ~GrAutoMalloc() { GrFree(fPtr); }
30
31 /**
32 * Return the allocated memory, or NULL if it has already been freed or
33 * detached.
34 */
35 void* get() const { return fPtr; }
36
bsalomon@google.com1c13c962011-02-14 16:51:21 +000037 size_t size() const { return fAllocatedBytes; }
38
reed@google.comac10a2d2010-12-22 21:39:39 +000039 /**
40 * transfer ownership of the memory to the caller. It must be freed with
41 * a call to GrFree()
42 */
43 void* detach() {
44 void* ptr = fPtr;
45 fPtr = NULL; // we no longer own the block
bsalomon@google.com1c13c962011-02-14 16:51:21 +000046 fAllocatedBytes = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +000047 return ptr;
48 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +000049
50 /**
51 * Reallocates to a new size. May or may not call malloc. The contents
52 * are not preserved. If growOnly is true it will never reduce the
53 * allocated size.
54 */
55 void* realloc(size_t newSize, bool growOnly = false) {
56 bool alloc;
57 if (growOnly) {
58 alloc = newSize > fAllocatedBytes;
59 } else {
60 alloc = newSize != fAllocatedBytes;
61 }
62 if (alloc) {
63 GrFree(fPtr);
64 fPtr = newSize ? GrMalloc(newSize) : NULL;
65 fAllocatedBytes = newSize;
66 }
67 GrAssert(fAllocatedBytes >= newSize);
68 GR_DEBUGCODE(memset(fPtr, 0xEF, fAllocatedBytes));
69 return fPtr;
70 }
71
reed@google.comac10a2d2010-12-22 21:39:39 +000072 /**
73 * free the block now. get() will now return NULL
74 */
75 void free() {
76 GrFree(fPtr);
77 fPtr = NULL;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000078 fAllocatedBytes = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +000079 }
80
81private:
82 void* fPtr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000083 size_t fAllocatedBytes;
reed@google.comac10a2d2010-12-22 21:39:39 +000084};
85
86/**
87 * Variant of GrAutoMalloc with a compile-time specified byte size that is
88 * pre-allocated in the class object, avoiding a call to to GrMalloc if
89 * possible.
90 */
91template <size_t SIZE> class GrAutoSMalloc : GrNoncopyable {
92public:
93 GrAutoSMalloc() {
94 fPtr = fStorage;
95 fAllocatedBytes = SIZE;
96 }
97
98 explicit GrAutoSMalloc(size_t bytes) {
99 if (bytes > SIZE) {
100 fPtr = GrMalloc(bytes);
101 fAllocatedBytes = bytes;
102 } else {
103 fPtr = fStorage;
104 fAllocatedBytes = SIZE;
105 }
106 }
107
108 ~GrAutoSMalloc() {
109 if (fPtr != (void*)fStorage) {
110 GrFree(fPtr);
111 }
112 }
113
114 /**
115 * Return the allocated memory, or NULL if it has already been freed or
116 * detached.
117 */
118 void* get() const { return fPtr; }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000119
reed@google.comac10a2d2010-12-22 21:39:39 +0000120 /**
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000121 * Reallocates to a new size. May or may not call malloc. The contents
122 * are not preserved. If growOnly is true it will never reduce the
reed@google.comac10a2d2010-12-22 21:39:39 +0000123 * allocated size.
124 */
125 void* realloc(size_t newSize, bool growOnly = false) {
126 if (newSize <= SIZE) {
127 if (NULL == fPtr) {
128 fPtr = fStorage;
129 fAllocatedBytes = SIZE;
130 } else if (!growOnly && fPtr != (void*)fStorage) {
131 GrFree(fPtr);
132 fPtr = fStorage;
133 fAllocatedBytes = SIZE;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000134 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000135 } else if ((newSize > fAllocatedBytes) ||
136 (!growOnly && newSize < (fAllocatedBytes >> 1))) {
137 if (NULL != fPtr && fPtr != (void*)fStorage) {
138 GrFree(fPtr);
139 }
140 fPtr = GrMalloc(newSize);
141 fAllocatedBytes = newSize;
142 }
143 GrAssert(fAllocatedBytes >= newSize);
144 GrAssert((fPtr == fStorage) == (fAllocatedBytes == SIZE));
145 GR_DEBUGCODE(memset(fPtr, 0xEF, fAllocatedBytes));
146 return fPtr;
147 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000148
reed@google.comac10a2d2010-12-22 21:39:39 +0000149 /**
150 * free the block now. get() will now return NULL
151 */
152 void free() {
153 if (fPtr != (void*)fStorage) {
154 GrFree(fPtr);
155 }
156 fAllocatedBytes = 0;
157 fPtr = NULL;
158 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000159
reed@google.comac10a2d2010-12-22 21:39:39 +0000160private:
161 void* fPtr;
162 uint32_t fAllocatedBytes;
163 uint32_t fStorage[GrALIGN4(SIZE) >> 2];
164};
165
166/**
167 * Variant of GrAutoMalloc with a compile-time specified byte size that is
168 * pre-allocated in the class object, avoiding a call to to GrMalloc if
169 * possible.
170 */
171template <int COUNT, typename T>
172class GrAutoSTMalloc : public GrAutoSMalloc<COUNT * sizeof(T)> {
173public:
174 GrAutoSTMalloc(int count) : GrAutoSMalloc<COUNT * sizeof(T)>(count * sizeof(T)) {}
175
176 operator T*() { return (T*)this->get(); }
177};
178
179
180#endif
181