Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google, Inc | 2 * Copyright 2014 Google, Inc |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef SkSmallAllocator_DEFINED | 8 #ifndef SkSmallAllocator_DEFINED |
| 9 #define SkSmallAllocator_DEFINED | 9 #define SkSmallAllocator_DEFINED |
| 10 | 10 |
| 11 #include "SkTDArray.h" | 11 #include "SkTDArray.h" |
| 12 #include "SkTypes.h" | 12 #include "SkTypes.h" |
| 13 | 13 |
| 14 #include <new> | 14 #include <new> |
|
mtklein_C
2016/11/06 13:25:16
Probably a good idea to include <utility>
herb_g
2016/11/07 04:44:40
Done.
| |
| 15 | 15 |
| 16 /* | 16 /* |
| 17 * Template class for allocating small objects without additional heap memory | 17 * Template class for allocating small objects without additional heap memory |
| 18 * allocations. kMaxObjects is a hard limit on the number of objects that can | 18 * allocations. kMaxObjects is a hard limit on the number of objects that can |
| 19 * be allocated using this class. After that, attempts to create more objects | 19 * be allocated using this class. After that, attempts to create more objects |
| 20 * with this class will assert and return nullptr. | 20 * with this class will assert and return nullptr. |
| 21 * | 21 * |
| 22 * kTotalBytes is the total number of bytes provided for storage for all | 22 * kTotalBytes is the total number of bytes provided for storage for all |
| 23 * objects created by this allocator. If an object to be created is larger | 23 * objects created by this allocator. If an object to be created is larger |
| 24 * than the storage (minus storage already used), it will be allocated on the | 24 * than the storage (minus storage already used), it will be allocated on the |
| 25 * heap. This class's destructor will handle calling the destructor for each | 25 * heap. This class's destructor will handle calling the destructor for each |
| 26 * object it allocated and freeing its memory. | 26 * object it allocated and freeing its memory. |
| 27 * | 27 * |
| 28 * Current the class always aligns each allocation to 16-bytes to be safe, but future | 28 * Current the class always aligns each allocation to 16-bytes to be safe, but future |
| 29 * may reduce this to only the alignment that is required per alloc. | 29 * may reduce this to only the alignment that is required per alloc. |
| 30 */ | 30 */ |
| 31 template<uint32_t kMaxObjects, size_t kTotalBytes> | 31 template<uint32_t kMaxObjects, size_t kTotalBytes> |
| 32 class SkSmallAllocator : SkNoncopyable { | 32 class SkSmallAllocator : SkNoncopyable { |
| 33 public: | 33 public: |
| 34 SkSmallAllocator() | 34 SkSmallAllocator() |
| 35 : fStorageUsed(0) | 35 : fStorageUsed(0) |
| 36 , fNumObjects(0) | 36 , fNumObjects(0) { } |
| 37 {} | |
|
mtklein_C
2016/11/06 13:25:16
Seems unnecessary?
herb_g
2016/11/07 04:44:40
Done.
| |
| 38 | 37 |
| 39 ~SkSmallAllocator() { | 38 ~SkSmallAllocator() { |
| 40 // Destruct in reverse order, in case an earlier object points to a | 39 // Destruct in reverse order, in case an earlier object points to a |
| 41 // later object. | 40 // later object. |
| 42 while (fNumObjects > 0) { | 41 while (fNumObjects > 0) { |
| 43 fNumObjects--; | 42 fNumObjects--; |
| 44 Rec* rec = &fRecs[fNumObjects]; | 43 Rec* rec = &fRecs[fNumObjects]; |
| 45 rec->fKillProc(rec->fObj); | 44 rec->fKillProc(rec->fObj); |
| 46 // Safe to do if fObj is in fStorage, since fHeapStorage will | 45 // Safe to do if fObj is in fStorage, since fHeapStorage will |
| 47 // point to nullptr. | 46 // point to nullptr. |
| 48 sk_free(rec->fHeapStorage); | 47 sk_free(rec->fHeapStorage); |
| 49 } | 48 } |
| 50 } | 49 } |
| 51 | 50 |
| 52 /* | 51 /* |
| 53 * Create a new object of type T. Its lifetime will be handled by this | 52 * Create a new object of type T. Its lifetime will be handled by this |
| 54 * SkSmallAllocator. | 53 * SkSmallAllocator. |
| 55 * Note: If kMaxObjects have been created by this SkSmallAllocator, nullptr | 54 * Note: If kMaxObjects have been created by this SkSmallAllocator, nullptr |
| 56 * will be returned. | 55 * will be returned. |
| 57 */ | 56 */ |
| 58 template<typename T, typename... Args> | 57 template<typename T, typename... Args> |
| 59 T* createT(const Args&... args) { | 58 T* createT(Args&&... args) { |
| 60 void* buf = this->reserveT<T>(); | 59 void* buf = this->reserveT<T>(); |
| 61 if (nullptr == buf) { | 60 if (nullptr == buf) { |
| 62 return nullptr; | 61 return nullptr; |
| 63 } | 62 } |
| 64 return new (buf) T(args...); | 63 return new (buf) T(std::forward<Args>(args)...); |
| 65 } | 64 } |
| 66 | 65 |
| 67 /* | 66 /* |
| 68 * Reserve a specified amount of space (must be enough space for one T). | 67 * Reserve a specified amount of space (must be enough space for one T). |
| 69 * The space will be in fStorage if there is room, or on the heap otherwise . | 68 * The space will be in fStorage if there is room, or on the heap otherwise . |
| 70 * Either way, this class will call ~T() in its destructor and free the hea p | 69 * Either way, this class will call ~T() in its destructor and free the hea p |
| 71 * allocation if necessary. | 70 * allocation if necessary. |
| 72 * Unlike createT(), this method will not call the constructor of T. | 71 * Unlike createT(), this method will not call the constructor of T. |
| 73 */ | 72 */ |
| 74 template<typename T> void* reserveT(size_t storageRequired = sizeof(T)) { | 73 template<typename T> void* reserveT(size_t storageRequired = sizeof(T)) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 void freeLast() { | 108 void freeLast() { |
| 110 SkASSERT(fNumObjects > 0); | 109 SkASSERT(fNumObjects > 0); |
| 111 Rec* rec = &fRecs[fNumObjects - 1]; | 110 Rec* rec = &fRecs[fNumObjects - 1]; |
| 112 sk_free(rec->fHeapStorage); | 111 sk_free(rec->fHeapStorage); |
| 113 fStorageUsed -= rec->fStorageSize; | 112 fStorageUsed -= rec->fStorageSize; |
| 114 | 113 |
| 115 fNumObjects--; | 114 fNumObjects--; |
| 116 } | 115 } |
| 117 | 116 |
| 118 private: | 117 private: |
| 118 static constexpr size_t kAlignment = 16UL; | |
|
mtklein_C
2016/11/06 13:25:16
Unused?
herb_g
2016/11/07 04:44:40
Done.
| |
| 119 struct Rec { | 119 struct Rec { |
| 120 size_t fStorageSize; // 0 if allocated on heap | 120 size_t fStorageSize; // 0 if allocated on heap |
| 121 void* fObj; | 121 void* fObj; |
| 122 void* fHeapStorage; | 122 void* fHeapStorage; |
| 123 void (*fKillProc)(void*); | 123 void (*fKillProc)(void*); |
| 124 }; | 124 }; |
| 125 | 125 |
| 126 // Used to call the destructor for allocated objects. | 126 // Used to call the destructor for allocated objects. |
| 127 template<typename T> | 127 template<typename T> |
| 128 static void DestroyT(void* ptr) { | 128 static void DestroyT(void* ptr) { |
| 129 static_cast<T*>(ptr)->~T(); | 129 static_cast<T*>(ptr)->~T(); |
| 130 } | 130 } |
| 131 | 131 |
| 132 alignas(16) char fStorage[kTotalBytes]; | 132 alignas(16) char fStorage[kTotalBytes]; |
| 133 // Number of bytes used so far. | 133 size_t fStorageUsed; // Number of bytes used so far. |
| 134 size_t fStorageUsed; | 134 uint32_t fNumObjects; |
| 135 uint32_t fNumObjects; | 135 Rec fRecs[kMaxObjects]; |
| 136 Rec fRecs[kMaxObjects]; | |
| 137 }; | 136 }; |
| 138 | 137 |
| 139 #endif // SkSmallAllocator_DEFINED | 138 #endif // SkSmallAllocator_DEFINED |
| OLD | NEW |