blob: c4bca241d77fbc49b8a54d2dc373cfd74f3a6935 [file] [log] [blame]
reed@google.com80ba7962012-07-21 17:31:40 +00001//
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
reed@google.comf7943032012-07-23 14:50:38 +000012#include "SkRefCnt.h"
reed@google.com0c6a7362012-07-21 19:39:24 +000013#include <new>
reed@google.com80ba7962012-07-21 17:31:40 +000014
15/**
16 * Wrapper to manage thread-safe sharing of an array of T objects. The array
17 * cannot be grown or shrunk.
18 */
reed@google.comf7943032012-07-23 14:50:38 +000019template <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
reed@google.com80ba7962012-07-21 17:31:40 +000027 size_t size = sizeof(SkTRefArray<T>) + count * sizeof(T);
28 SkTRefArray<T>* obj = (SkTRefArray<T>*)sk_malloc_throw(size);
rmistry@google.comfbfcd562012-08-23 18:09:54 +000029
reed@google.comf7943032012-07-23 14:50:38 +000030 SkNEW_PLACEMENT(obj, SkTRefArray<T>);
reed@google.com80ba7962012-07-21 17:31:40 +000031 obj->fCount = count;
reed@google.com80ba7962012-07-21 17:31:40 +000032 return obj;
33 }
34
reed@google.comf7943032012-07-23 14:50:38 +000035public:
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 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000049
reed@google.comf7943032012-07-23 14:50:38 +000050 /**
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 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000063
reed@google.com80ba7962012-07-21 17:31:40 +000064 int count() const { return fCount; }
65 const T* begin() const { return (const T*)(this + 1); }
reed@google.comf7943032012-07-23 14:50:38 +000066 const T* end() const { return this->begin() + fCount; }
67 const T& at(int index) const {
reed@google.com80ba7962012-07-21 17:31:40 +000068 SkASSERT((unsigned)index < (unsigned)fCount);
69 return this->begin()[index];
70 }
reed@google.comf7943032012-07-23 14:50:38 +000071 const T& operator[](int index) const { return this->at(index); }
reed@google.com80ba7962012-07-21 17:31:40 +000072
reed@google.comf7943032012-07-23 14:50:38 +000073 // 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.
reed@google.com80ba7962012-07-21 17:31:40 +000075
reed@google.comf7943032012-07-23 14:50:38 +000076 T* writableBegin() {
bungeman@google.comf64c6842013-07-19 23:18:52 +000077 SkASSERT(this->unique());
reed@google.comf7943032012-07-23 14:50:38 +000078 return (T*)(this + 1);
reed@google.com80ba7962012-07-21 17:31:40 +000079 }
reed@google.comf7943032012-07-23 14:50:38 +000080 T* writableEnd() {
81 return this->writableBegin() + fCount;
82 }
83 T& writableAt(int index) {
84 SkASSERT((unsigned)index < (unsigned)fCount);
85 return this->writableBegin()[index];
reed@google.com80ba7962012-07-21 17:31:40 +000086 }
87
reed@google.comf7943032012-07-23 14:50:38 +000088protected:
89 virtual void internal_dispose() const SK_OVERRIDE {
reed@google.com80ba7962012-07-21 17:31:40 +000090 T* array = const_cast<T*>(this->begin());
91 int n = fCount;
rmistry@google.comfbfcd562012-08-23 18:09:54 +000092
reed@google.com80ba7962012-07-21 17:31:40 +000093 for (int i = 0; i < n; ++i) {
94 array->~T();
95 array += 1;
96 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000097
reed@google.comf7943032012-07-23 14:50:38 +000098 this->internal_dispose_restore_refcnt_to_1();
99 this->~SkTRefArray<T>();
100 sk_free((void*)this);
reed@google.com80ba7962012-07-21 17:31:40 +0000101 }
reed@google.comf7943032012-07-23 14:50:38 +0000102
103private:
104 int fCount;
105
106 // hide this
107 virtual ~SkTRefArray() {}
108
109 typedef SkRefCnt INHERITED;
reed@google.com80ba7962012-07-21 17:31:40 +0000110};
111
112#endif