// // SkTRefArray.h // core // // Created by Mike Reed on 7/17/12. // Copyright (c) 2012 __MyCompanyName__. All rights reserved. // #ifndef SkTRefArray_DEFINED #define SkTRefArray_DEFINED #include "SkRefCnt.h" #include /** * Wrapper to manage thread-safe sharing of an array of T objects. The array * cannot be grown or shrunk. */ template class SkTRefArray : public SkRefCnt { /* * Shared factory to allocate the space needed for our instance plus N * T entries at the end. We call our constructor, but not the constructors * for the elements. Those are called by the proper Create method. */ static SkTRefArray* Alloc(int count) { // space for us, and our [count] elements size_t size = sizeof(SkTRefArray) + count * sizeof(T); SkTRefArray* obj = (SkTRefArray*)sk_malloc_throw(size); SkNEW_PLACEMENT(obj, SkTRefArray); obj->fCount = count; return obj; } public: /** * Return a new array with 'count' elements, initialized to their default * value. To change them to some other value, use writableBegin/End or * writableAt(), but do that before this array is given to another thread. */ static SkTRefArray* Create(int count) { SkTRefArray* obj = Alloc(count); T* array = const_cast(obj->begin()); for (int i = 0; i < count; ++i) { SkNEW_PLACEMENT(&array[i], T); } return obj; } /** * Return a new array with 'count' elements, initialized from the provided * src array. To change them to some other value, use writableBegin/End or * writableAt(), but do that before this array is given to another thread. */ static SkTRefArray* Create(const T src[], int count) { SkTRefArray* obj = Alloc(count); T* array = const_cast(obj->begin()); for (int i = 0; i < count; ++i) { SkNEW_PLACEMENT_ARGS(&array[i], T, (src[i])); } return obj; } int count() const { return fCount; } const T* begin() const { return (const T*)(this + 1); } const T* end() const { return this->begin() + fCount; } const T& at(int index) const { SkASSERT((unsigned)index < (unsigned)fCount); return this->begin()[index]; } const T& operator[](int index) const { return this->at(index); } // For the writable methods, we assert that we are the only owner if we // call these, since other owners are not informed if we change an element. T* writableBegin() { SkASSERT(this->unique()); return (T*)(this + 1); } T* writableEnd() { return this->writableBegin() + fCount; } T& writableAt(int index) { SkASSERT((unsigned)index < (unsigned)fCount); return this->writableBegin()[index]; } protected: virtual void internal_dispose() const SK_OVERRIDE { T* array = const_cast(this->begin()); int n = fCount; for (int i = 0; i < n; ++i) { array->~T(); array += 1; } this->internal_dispose_restore_refcnt_to_1(); this->~SkTRefArray(); sk_free((void*)this); } private: int fCount; // hide this virtual ~SkTRefArray() {} typedef SkRefCnt INHERITED; }; #endif