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 template <typename T> class SkAutoTDelete : SkNoncopyable {
     63 public:
     64     SkAutoTDelete(T* obj) : fObj(obj) {}
     65     ~SkAutoTDelete() { delete fObj; }
     66 
     67     T*      get() const { return fObj; }
     68     void    free() { delete fObj; fObj = NULL; }
     69     T*      detach() { T* obj = fObj; fObj = NULL; return obj; }
     70 
     71 private:
     72     T*  fObj;
     73 };
     74 
     75 template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
     76 public:
     77     SkAutoTDeleteArray(T array[]) : fArray(array) {}
     78     ~SkAutoTDeleteArray() { delete[] fArray; }
     79 
     80     T*      get() const { return fArray; }
     81     void    free() { delete[] fArray; fArray = NULL; }
     82     T*      detach() { T* array = fArray; fArray = NULL; return array; }
     83 
     84 private:
     85     T*  fArray;
     86 };
     87 
     88 /** Allocate an array of T elements, and free the array in the destructor
     89  */
     90 template <typename T> class SkAutoTArray : SkNoncopyable {
     91 public:
     92     /** Allocate count number of T elements
     93      */
     94     SkAutoTArray(size_t count) {
     95         fArray = NULL;
     96         if (count) {
     97             fArray = new T[count];
     98         }
     99         SkDEBUGCODE(fCount = count;)
    100     }
    101 
    102     ~SkAutoTArray() {
    103         delete[] fArray;
    104     }
    105 
    106     /** Return the array of T elements. Will be NULL if count == 0
    107      */
    108     T* get() const { return fArray; }
    109 
    110     /** Return the nth element in the array
    111      */
    112     T&  operator[](int index) const {
    113         SkASSERT((unsigned)index < fCount);
    114         return fArray[index];
    115     }
    116 
    117 private:
    118     T*  fArray;
    119     SkDEBUGCODE(size_t fCount;)
    120 };
    121 
    122 /** Wraps SkAutoTArray, with room for up to N elements preallocated
    123  */
    124 template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable {
    125 public:
    126     /** Allocate count number of T elements
    127      */
    128     SkAutoSTArray(size_t count) {
    129         if (count > N) {
    130             fArray = new T[count];
    131         } else if (count) {
    132             fArray = new (fStorage) T[count];
    133         } else {
    134             fArray = NULL;
    135         }
    136         fCount = count;
    137     }
    138 
    139     ~SkAutoSTArray() {
    140         if (fCount > N) {
    141             delete[] fArray;
    142         } else {
    143             T* start = fArray;
    144             T* iter = start + fCount;
    145             while (iter > start) {
    146                 (--iter)->~T();
    147             }
    148         }
    149     }
    150 
    151     /** Return the number of T elements in the array
    152      */
    153     size_t count() const { return fCount; }
    154 
    155     /** Return the array of T elements. Will be NULL if count == 0
    156      */
    157     T* get() const { return fArray; }
    158 
    159     /** Return the nth element in the array
    160      */
    161     T&  operator[](int index) const {
    162         SkASSERT((unsigned)index < fCount);
    163         return fArray[index];
    164     }
    165 
    166 private:
    167     size_t  fCount;
    168     T*      fArray;
    169     // since we come right after fArray, fStorage should be properly aligned
    170     char    fStorage[N * sizeof(T)];
    171 };
    172 
    173 /** Allocate a temp array on the stack/heap.
    174     Does NOT call any constructors/destructors on T (i.e. T must be POD)
    175 */
    176 template <typename T> class SkAutoTMalloc : SkNoncopyable {
    177 public:
    178     SkAutoTMalloc(size_t count)
    179     {
    180         fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
    181     }
    182     ~SkAutoTMalloc()
    183     {
    184         sk_free(fPtr);
    185     }
    186     T* get() const { return fPtr; }
    187 
    188 private:
    189     T*  fPtr;
    190 };
    191 
    192 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable {
    193 public:
    194     SkAutoSTMalloc(size_t count)
    195     {
    196         if (count <= N)
    197             fPtr = fTStorage;
    198         else
    199             fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
    200     }
    201     ~SkAutoSTMalloc()
    202     {
    203         if (fPtr != fTStorage)
    204             sk_free(fPtr);
    205     }
    206     T* get() const { return fPtr; }
    207 
    208 private:
    209     T*          fPtr;
    210     union {
    211         uint32_t    fStorage32[(N*sizeof(T) + 3) >> 2];
    212         T           fTStorage[1];   // do NOT want to invoke T::T()
    213     };
    214 };
    215 
    216 #endif
    217 
    218