Home | History | Annotate | Download | only in core
      1 //
      2 //  SkTRefArray.h
      3 //  core
      4 //
      5 //  Created by Mike Reed on 7/17/12.
      6 //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
      7 //
      8 
      9 #ifndef SkTRefArray_DEFINED
     10 #define SkTRefArray_DEFINED
     11 
     12 #include "SkRefCnt.h"
     13 #include <new>
     14 
     15 /**
     16  *  Wrapper to manage thread-safe sharing of an array of T objects. The array
     17  *  cannot be grown or shrunk.
     18  */
     19 template <typename T> class SkTRefArray : public SkRefCnt {
     20     /*
     21      *  Shared factory to allocate the space needed for our instance plus N
     22      *  T entries at the end. We call our constructor, but not the constructors
     23      *  for the elements. Those are called by the proper Create method.
     24      */
     25     static SkTRefArray<T>* Alloc(int count) {
     26         // space for us, and our [count] elements
     27         size_t size = sizeof(SkTRefArray<T>) + count * sizeof(T);
     28         SkTRefArray<T>* obj = (SkTRefArray<T>*)sk_malloc_throw(size);
     29 
     30         SkNEW_PLACEMENT(obj, SkTRefArray<T>);
     31         obj->fCount = count;
     32         return obj;
     33     }
     34 
     35 public:
     36     /**
     37      *  Return a new array with 'count' elements, initialized to their default
     38      *  value. To change them to some other value, use writableBegin/End or
     39      *  writableAt(), but do that before this array is given to another thread.
     40      */
     41     static SkTRefArray<T>* Create(int count) {
     42         SkTRefArray<T>* obj = Alloc(count);
     43         T* array = const_cast<T*>(obj->begin());
     44         for (int i = 0; i < count; ++i) {
     45             SkNEW_PLACEMENT(&array[i], T);
     46         }
     47         return obj;
     48     }
     49 
     50     /**
     51      *  Return a new array with 'count' elements, initialized from the provided
     52      *  src array. To change them to some other value, use writableBegin/End or
     53      *  writableAt(), but do that before this array is given to another thread.
     54      */
     55     static SkTRefArray<T>* Create(const T src[], int count) {
     56         SkTRefArray<T>* obj = Alloc(count);
     57         T* array = const_cast<T*>(obj->begin());
     58         for (int i = 0; i < count; ++i) {
     59             SkNEW_PLACEMENT_ARGS(&array[i], T, (src[i]));
     60         }
     61         return obj;
     62     }
     63 
     64     int count() const { return fCount; }
     65     const T* begin() const { return (const T*)(this + 1); }
     66     const T* end() const { return this->begin() + fCount; }
     67     const T& at(int index) const {
     68         SkASSERT((unsigned)index < (unsigned)fCount);
     69         return this->begin()[index];
     70     }
     71     const T& operator[](int index) const { return this->at(index); }
     72 
     73     // For the writable methods, we assert that we are the only owner if we
     74     // call these, since other owners are not informed if we change an element.
     75 
     76     T* writableBegin() {
     77         SkASSERT(this->unique());
     78         return (T*)(this + 1);
     79     }
     80     T* writableEnd() {
     81         return this->writableBegin() + fCount;
     82     }
     83     T& writableAt(int index) {
     84         SkASSERT((unsigned)index < (unsigned)fCount);
     85         return this->writableBegin()[index];
     86     }
     87 
     88 protected:
     89     virtual void internal_dispose() const SK_OVERRIDE {
     90         T* array = const_cast<T*>(this->begin());
     91         int n = fCount;
     92 
     93         for (int i = 0; i < n; ++i) {
     94             array->~T();
     95             array += 1;
     96         }
     97 
     98         this->internal_dispose_restore_refcnt_to_1();
     99         this->~SkTRefArray<T>();
    100         sk_free((void*)this);
    101     }
    102 
    103 private:
    104     int fCount;
    105 
    106     // hide this
    107     virtual ~SkTRefArray() {}
    108 
    109     typedef SkRefCnt INHERITED;
    110 };
    111 
    112 #endif
    113