diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/core/SkTRefArray.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/core/SkTRefArray.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,112 @@ +// +// 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