Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright 2014 Google, Inc | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 // FIXME: Move to SkSmallAllocator.h | |
|
mtklein
2014/03/05 20:59:56
:) I have found writing a git-fr (find-replace) s
| |
| 9 #ifndef SkSmallAllocator_DEFINED | |
| 10 #define SkSmallAllocator_DEFINED | |
| 11 | |
| 12 #include "SkTDArray.h" | |
| 13 #include "SkTypes.h" | |
| 14 | |
| 15 // Used by SkSmallAllocator to call the destructor for objects it has | |
| 16 // allocated. | |
| 17 template<typename T> void destroyT(void* ptr) { | |
| 18 static_cast<T*>(ptr)->~T(); | |
| 19 } | |
| 20 | |
| 21 /* | |
| 22 * Template class for allocating small objects without additional heap memory | |
| 23 * allocations. kMaxObjects is a hard limit on the number of objects that can | |
| 24 * be allocated using this class. After that, attempts to create more objects | |
| 25 * with this class will return NULL. | |
| 26 * kBytes is the number of bytes provided for storage. If an object is larger | |
|
mtklein
2014/03/05 20:59:56
It's kBytes total? Or kBytes per object? E.g. if
scroggo
2014/03/05 23:23:26
I thought this was pretty clear, but I've changed
mtklein
2014/03/06 15:04:07
Thanks! I am no longer confused. I see now this
| |
| 27 * than the storage (minus storage already used), it will be allocated on the | |
|
mtklein
2014/03/05 20:59:56
Can we get away with a hard failure like for count
scroggo
2014/03/05 23:23:26
That's a good idea. Added an assert for too many o
mtklein
2014/03/06 15:04:07
Hmm, that's a good point. It'd be easy to see a h
scroggo
2014/03/06 18:07:04
That sounds like a good compromise. Done. I didn't
| |
| 28 * heap. This class's destructor will handle calling the destructor for each | |
| 29 * object it allocated and freeing its memory. | |
| 30 */ | |
| 31 template<uint32_t kMaxObjects, size_t kBytes> | |
| 32 class SkSmallAllocator : public SkNoncopyable { | |
| 33 public: | |
| 34 SkSmallAllocator() | |
| 35 : fStorageUsed(0) | |
| 36 , fNumObjects(0) | |
| 37 {} | |
| 38 | |
| 39 ~SkSmallAllocator() { | |
| 40 // Destruct in reverse order, in case an earlier object points to a | |
| 41 // later object. | |
| 42 while (fNumObjects > 0) { | |
| 43 fNumObjects--; | |
| 44 Rec* rec = &fRecs[fNumObjects]; | |
| 45 rec->fKillProc(rec->fObj); | |
| 46 // Safe to do if fObj is in fStorage, since fHeapStorage will | |
| 47 // point to NULL. | |
| 48 sk_free(rec->fHeapStorage); | |
| 49 } | |
| 50 } | |
| 51 | |
| 52 /* | |
| 53 * Create a new object of type T. Its lifetime will be handled by this | |
| 54 * SkSmallAllocator. | |
| 55 * Each version behaves the same but takes a different number of | |
| 56 * arguments. | |
| 57 * Note: If kMaxObjects have been created by this SkSmallAllocator, NULL | |
| 58 * will be returned. | |
| 59 */ | |
| 60 template<typename T> T* createT() { | |
|
mtklein
2014/03/05 20:59:56
Might want to break the line after > for all of th
scroggo
2014/03/05 23:23:26
Done.
| |
| 61 void* buf = this->reserveT<T>(); | |
| 62 if (NULL == buf) { | |
| 63 return NULL; | |
| 64 } | |
| 65 SkNEW_PLACEMENT(buf, T); | |
| 66 return static_cast<T*>(buf); | |
| 67 } | |
| 68 | |
| 69 template<typename T, typename A1> T* createT(const A1& a1) { | |
| 70 void* buf = this->reserveT<T>(); | |
| 71 if (NULL == buf) { | |
| 72 return NULL; | |
| 73 } | |
| 74 SkNEW_PLACEMENT_ARGS(buf, T, (a1)); | |
| 75 return static_cast<T*>(buf); | |
| 76 } | |
| 77 | |
| 78 template<typename T, typename A1, typename A2> | |
| 79 T* createT(const A1& a1, const A2& a2) { | |
| 80 void* buf = this->reserveT<T>(); | |
| 81 if (NULL == buf) { | |
| 82 return NULL; | |
| 83 } | |
| 84 SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2)); | |
| 85 return static_cast<T*>(buf); | |
| 86 } | |
| 87 | |
| 88 template<typename T, typename A1, typename A2, typename A3> | |
| 89 T* createT(const A1& a1, const A2& a2, const A3& a3) { | |
| 90 void* buf = this->reserveT<T>(); | |
| 91 if (NULL == buf) { | |
| 92 return NULL; | |
| 93 } | |
| 94 SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3)); | |
| 95 return static_cast<T*>(buf); | |
| 96 } | |
| 97 | |
| 98 private: | |
| 99 /* | |
| 100 * Helper function to provide space for one T. The space will be in | |
| 101 * fStorage if there is room, or on the heap otherwise. Either way, this | |
| 102 * class will call ~T() in its destructor and free the heap allocation if | |
| 103 * necessary. | |
| 104 */ | |
| 105 template<typename T> void* reserveT() { | |
| 106 SkASSERT(fNumObjects <= kMaxObjects); | |
| 107 if (kMaxObjects == fNumObjects) { | |
| 108 return NULL; | |
| 109 } | |
| 110 const size_t storageRemaining = SkAlign4(kBytes) - fStorageUsed; | |
| 111 const size_t storageRequired = SkAlign4(sizeof(T)); | |
| 112 Rec* rec = &fRecs[fNumObjects]; | |
| 113 if (storageRequired > storageRemaining) { | |
| 114 // Allocate on the heap | |
| 115 rec->fHeapStorage = sk_malloc_throw(storageRequired); | |
| 116 rec->fObj = static_cast<void*>(rec->fHeapStorage); | |
| 117 } else { | |
| 118 // There is space in fStorage. | |
| 119 rec->fHeapStorage = NULL; | |
| 120 SkASSERT(SkIsAlign4(fStorageUsed)); | |
| 121 rec->fObj = static_cast<void*>(fStorage + (fStorageUsed >> 2)); | |
|
mtklein
2014/03/05 20:59:56
I'm developing a preference for / 4 unless the arg
scroggo
2014/03/05 23:23:26
Done.
| |
| 122 fStorageUsed += storageRequired; | |
| 123 } | |
| 124 rec->fKillProc = destroyT<T>; | |
| 125 fNumObjects++; | |
| 126 return rec->fObj; | |
| 127 } | |
| 128 | |
| 129 private: | |
| 130 struct Rec { | |
| 131 void* fObj; | |
|
mtklein
2014/03/05 20:59:56
Now that I'm thinking about it, it's probably not
| |
| 132 void* fHeapStorage; | |
| 133 void (*fKillProc)(void*); | |
| 134 }; | |
| 135 | |
| 136 // Number of bytes used so far. | |
| 137 size_t fStorageUsed; | |
| 138 // Pad the storage size to be 4-byte aligned. | |
| 139 uint32_t fStorage[SkAlign4(kBytes) >> 2]; | |
| 140 uint32_t fNumObjects; | |
| 141 Rec fRecs[kMaxObjects]; | |
| 142 }; | |
| 143 | |
| 144 #endif // SkSmallAllocator_DEFINED | |
| OLD | NEW |