Home | History | Annotate | Download | only in include
      1 /*
      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 
     23 class GrAutoMalloc : GrNoncopyable {
     24 public:
     25     GrAutoMalloc() : fPtr(NULL), fAllocatedBytes(0){
     26     }
     27 
     28     GrAutoMalloc(size_t bytes) : fPtr(GrMalloc(bytes)), fAllocatedBytes(bytes) {}
     29     ~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 
     37     size_t size() const { return fAllocatedBytes; }
     38 
     39     /**
     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
     46         fAllocatedBytes = 0;
     47         return ptr;
     48     }
     49 
     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 
     72     /**
     73      *  free the block now. get() will now return NULL
     74      */
     75     void free() {
     76         GrFree(fPtr);
     77         fPtr = NULL;
     78         fAllocatedBytes = 0;
     79     }
     80 
     81 private:
     82     void* fPtr;
     83     size_t fAllocatedBytes;
     84 };
     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  */
     91 template <size_t SIZE> class GrAutoSMalloc : GrNoncopyable {
     92 public:
     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; }
    119 
    120     /**
    121      *  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
    123      *  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;
    134             }
    135         } 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     }
    148 
    149     /**
    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     }
    159 
    160 private:
    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  */
    171 template <int COUNT, typename T>
    172 class GrAutoSTMalloc : public GrAutoSMalloc<COUNT * sizeof(T)> {
    173 public:
    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 
    182