180ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com// 280ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com// SkTRefArray.h 380ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com// core 480ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com// 580ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com// Created by Mike Reed on 7/17/12. 680ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com// Copyright (c) 2012 __MyCompanyName__. All rights reserved. 780ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com// 880ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com 980ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com#ifndef SkTRefArray_DEFINED 1080ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com#define SkTRefArray_DEFINED 1180ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com 12f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com#include "SkRefCnt.h" 130c6a736617d242547135b731adb8333581b2f2dcreed@google.com#include <new> 1480ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com 1580ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com/** 1680ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com * Wrapper to manage thread-safe sharing of an array of T objects. The array 1780ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com * cannot be grown or shrunk. 1880ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com */ 19f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comtemplate <typename T> class SkTRefArray : public SkRefCnt { 20f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /* 21f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Shared factory to allocate the space needed for our instance plus N 22f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * T entries at the end. We call our constructor, but not the constructors 23f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * for the elements. Those are called by the proper Create method. 24f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 25f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com static SkTRefArray<T>* Alloc(int count) { 26f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com // space for us, and our [count] elements 2780ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com size_t size = sizeof(SkTRefArray<T>) + count * sizeof(T); 2880ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com SkTRefArray<T>* obj = (SkTRefArray<T>*)sk_malloc_throw(size); 29fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 30f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkNEW_PLACEMENT(obj, SkTRefArray<T>); 3180ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com obj->fCount = count; 32f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com return obj; 33f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 340c6a736617d242547135b731adb8333581b2f2dcreed@google.com 35f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.compublic: 36f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 37f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Return a new array with 'count' elements, initialized to their default 38f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * value. To change them to some other value, use writableBegin/End or 39f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * writableAt(), but do that before this array is given to another thread. 40f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 41f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com static SkTRefArray<T>* Create(int count) { 42f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkTRefArray<T>* obj = Alloc(count); 4380ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com T* array = const_cast<T*>(obj->begin()); 4480ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com for (int i = 0; i < count; ++i) { 45f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkNEW_PLACEMENT(&array[i], T); 4680ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com } 4780ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com return obj; 4880ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com } 49fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 50f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 51f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Return a new array with 'count' elements, initialized from the provided 52f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * src array. To change them to some other value, use writableBegin/End or 53f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * writableAt(), but do that before this array is given to another thread. 54f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 55f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com static SkTRefArray<T>* Create(const T src[], int count) { 56f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkTRefArray<T>* obj = Alloc(count); 57f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com T* array = const_cast<T*>(obj->begin()); 58f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com for (int i = 0; i < count; ++i) { 59f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkNEW_PLACEMENT_ARGS(&array[i], T, (src[i])); 60f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 61f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com return obj; 62f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 63fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 6480ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com int count() const { return fCount; } 6580ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com const T* begin() const { return (const T*)(this + 1); } 66f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com const T* end() const { return this->begin() + fCount; } 67f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com const T& at(int index) const { 6880ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 6980ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com return this->begin()[index]; 7080ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com } 71f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com const T& operator[](int index) const { return this->at(index); } 7280ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com 73f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com // For the writable methods, we assert that we are the only owner if we 74f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com // call these, since other owners are not informed if we change an element. 7580ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com 76f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com T* writableBegin() { 77f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com SkASSERT(this->unique()); 78f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com return (T*)(this + 1); 7980ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com } 80f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com T* writableEnd() { 81f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com return this->writableBegin() + fCount; 82f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 83f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com T& writableAt(int index) { 84f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 85f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com return this->writableBegin()[index]; 8680ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com } 8780ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com 88f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected: 89f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com virtual void internal_dispose() const SK_OVERRIDE { 9080ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com T* array = const_cast<T*>(this->begin()); 9180ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com int n = fCount; 92fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9380ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com for (int i = 0; i < n; ++i) { 9480ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com array->~T(); 9580ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com array += 1; 9680ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com } 97fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 98f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com this->internal_dispose_restore_refcnt_to_1(); 99f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com this->~SkTRefArray<T>(); 100f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com sk_free((void*)this); 10180ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com } 102f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 103f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate: 104f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com int fCount; 105f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 106f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com // hide this 107f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com virtual ~SkTRefArray() {} 108f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 109f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com typedef SkRefCnt INHERITED; 11080ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com}; 11180ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com 11280ba7964cde0f7805d76cf0170cf3b920146a007reed@google.com#endif 113