Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      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 #ifndef SkTemplates_DEFINED
     18 #define SkTemplates_DEFINED
     19 
     20 #include "SkTypes.h"
     21 
     22 /** \file SkTemplates.h
     23 
     24     This file contains light-weight template classes for type-safe and exception-safe
     25     resource management.
     26 */
     27 
     28 /** \class SkAutoTCallVProc
     29 
     30     Call a function when this goes out of scope. The template uses two
     31     parameters, the object, and a function that is to be called in the destructor.
     32     If detach() is called, the object reference is set to null. If the object
     33     reference is null when the destructor is called, we do not call the
     34     function.
     35 */
     36 template <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable {
     37 public:
     38     SkAutoTCallVProc(T* obj): fObj(obj) {}
     39     ~SkAutoTCallVProc() { if (fObj) P(fObj); }
     40     T* detach() { T* obj = fObj; fObj = NULL; return obj; }
     41 private:
     42     T* fObj;
     43 };
     44 
     45 /** \class SkAutoTCallIProc
     46 
     47 Call a function when this goes out of scope. The template uses two
     48 parameters, the object, and a function that is to be called in the destructor.
     49 If detach() is called, the object reference is set to null. If the object
     50 reference is null when the destructor is called, we do not call the
     51 function.
     52 */
     53 template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable {
     54 public:
     55     SkAutoTCallIProc(T* obj): fObj(obj) {}
     56     ~SkAutoTCallIProc() { if (fObj) P(fObj); }
     57     T* detach() { T* obj = fObj; fObj = NULL; return obj; }
     58 private:
     59     T* fObj;
     60 };
     61 
     62 // See also SkTScopedPtr.
     63 template <typename T> class SkAutoTDelete : SkNoncopyable {
     64 public:
     65     SkAutoTDelete(T* obj, bool deleteWhenDone = true) : fObj(obj) {
     66         fDeleteWhenDone = deleteWhenDone;
     67     }
     68     ~SkAutoTDelete() { if (fDeleteWhenDone) delete fObj; }
     69 
     70     T*      get() const { return fObj; }
     71     void    free() { delete fObj; fObj = NULL; }
     72     T*      detach() { T* obj = fObj; fObj = NULL; return obj; }
     73 
     74 private:
     75     T*  fObj;
     76     bool fDeleteWhenDone;
     77 };
     78 
     79 template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
     80 public:
     81     SkAutoTDeleteArray(T array[]) : fArray(array) {}
     82     ~SkAutoTDeleteArray() { delete[] fArray; }
     83 
     84     T*      get() const { return fArray; }
     85     void    free() { delete[] fArray; fArray = NULL; }
     86     T*      detach() { T* array = fArray; fArray = NULL; return array; }
     87 
     88 private:
     89     T*  fArray;
     90 };
     91 
     92 /** Allocate an array of T elements, and free the array in the destructor
     93  */
     94 template <typename T> class SkAutoTArray : SkNoncopyable {
     95 public:
     96     /** Allocate count number of T elements
     97      */
     98     SkAutoTArray(size_t count) {
     99         fArray = NULL;
    100         if (count) {
    101             fArray = new T[count];
    102         }
    103         SkDEBUGCODE(fCount = count;)
    104     }
    105 
    106     ~SkAutoTArray() {
    107         delete[] fArray;
    108     }
    109 
    110     /** Return the array of T elements. Will be NULL if count == 0
    111      */
    112     T* get() const { return fArray; }
    113 
    114     /** Return the nth element in the array
    115      */
    116     T&  operator[](int index) const {
    117         SkASSERT((unsigned)index < fCount);
    118         return fArray[index];
    119     }
    120 
    121 private:
    122     T*  fArray;
    123     SkDEBUGCODE(size_t fCount;)
    124 };
    125 
    126 /** Wraps SkAutoTArray, with room for up to N elements preallocated
    127  */
    128 template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable {
    129 public:
    130     /** Allocate count number of T elements
    131      */
    132     SkAutoSTArray(size_t count) {
    133         if (count > N) {
    134             fArray = new T[count];
    135         } else if (count) {
    136             fArray = new (fStorage) T[count];
    137         } else {
    138             fArray = NULL;
    139         }
    140         fCount = count;
    141     }
    142 
    143     ~SkAutoSTArray() {
    144         if (fCount > N) {
    145             delete[] fArray;
    146         } else {
    147             T* start = fArray;
    148             T* iter = start + fCount;
    149             while (iter > start) {
    150                 (--iter)->~T();
    151             }
    152         }
    153     }
    154 
    155     /** Return the number of T elements in the array
    156      */
    157     size_t count() const { return fCount; }
    158 
    159     /** Return the array of T elements. Will be NULL if count == 0
    160      */
    161     T* get() const { return fArray; }
    162 
    163     /** Return the nth element in the array
    164      */
    165     T&  operator[](int index) const {
    166         SkASSERT((unsigned)index < fCount);
    167         return fArray[index];
    168     }
    169 
    170 private:
    171     size_t  fCount;
    172     T*      fArray;
    173     // since we come right after fArray, fStorage should be properly aligned
    174     char    fStorage[N * sizeof(T)];
    175 };
    176 
    177 /** Allocate a temp array on the stack/heap.
    178     Does NOT call any constructors/destructors on T (i.e. T must be POD)
    179 */
    180 template <typename T> class SkAutoTMalloc : SkNoncopyable {
    181 public:
    182     SkAutoTMalloc(size_t count)
    183     {
    184         fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
    185     }
    186     ~SkAutoTMalloc()
    187     {
    188         sk_free(fPtr);
    189     }
    190     T* get() const { return fPtr; }
    191 
    192 private:
    193     T*  fPtr;
    194 };
    195 
    196 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable {
    197 public:
    198     SkAutoSTMalloc(size_t count)
    199     {
    200         if (count <= N)
    201             fPtr = fTStorage;
    202         else
    203             fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
    204     }
    205     ~SkAutoSTMalloc()
    206     {
    207         if (fPtr != fTStorage)
    208             sk_free(fPtr);
    209     }
    210     T* get() const { return fPtr; }
    211 
    212 private:
    213     T*          fPtr;
    214     union {
    215         uint32_t    fStorage32[(N*sizeof(T) + 3) >> 2];
    216         T           fTStorage[1];   // do NOT want to invoke T::T()
    217     };
    218 };
    219 
    220 #endif
    221 
    222