gfx/skia/trunk/src/core/SkSmallAllocator.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2014 Google, Inc
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #ifndef SkSmallAllocator_DEFINED
michael@0 9 #define SkSmallAllocator_DEFINED
michael@0 10
michael@0 11 #include "SkTDArray.h"
michael@0 12 #include "SkTypes.h"
michael@0 13
michael@0 14 // Used by SkSmallAllocator to call the destructor for objects it has
michael@0 15 // allocated.
michael@0 16 template<typename T> void destroyT(void* ptr) {
michael@0 17 static_cast<T*>(ptr)->~T();
michael@0 18 }
michael@0 19
michael@0 20 /*
michael@0 21 * Template class for allocating small objects without additional heap memory
michael@0 22 * allocations. kMaxObjects is a hard limit on the number of objects that can
michael@0 23 * be allocated using this class. After that, attempts to create more objects
michael@0 24 * with this class will assert and return NULL.
michael@0 25 * kTotalBytes is the total number of bytes provided for storage for all
michael@0 26 * objects created by this allocator. If an object to be created is larger
michael@0 27 * than the storage (minus storage already used), it will be allocated on the
michael@0 28 * heap. This class's destructor will handle calling the destructor for each
michael@0 29 * object it allocated and freeing its memory.
michael@0 30 */
michael@0 31 template<uint32_t kMaxObjects, size_t kTotalBytes>
michael@0 32 class SkSmallAllocator : public SkNoncopyable {
michael@0 33 public:
michael@0 34 SkSmallAllocator()
michael@0 35 : fStorageUsed(0)
michael@0 36 , fNumObjects(0)
michael@0 37 {}
michael@0 38
michael@0 39 ~SkSmallAllocator() {
michael@0 40 // Destruct in reverse order, in case an earlier object points to a
michael@0 41 // later object.
michael@0 42 while (fNumObjects > 0) {
michael@0 43 fNumObjects--;
michael@0 44 Rec* rec = &fRecs[fNumObjects];
michael@0 45 rec->fKillProc(rec->fObj);
michael@0 46 // Safe to do if fObj is in fStorage, since fHeapStorage will
michael@0 47 // point to NULL.
michael@0 48 sk_free(rec->fHeapStorage);
michael@0 49 }
michael@0 50 }
michael@0 51
michael@0 52 /*
michael@0 53 * Create a new object of type T. Its lifetime will be handled by this
michael@0 54 * SkSmallAllocator.
michael@0 55 * Each version behaves the same but takes a different number of
michael@0 56 * arguments.
michael@0 57 * Note: If kMaxObjects have been created by this SkSmallAllocator, NULL
michael@0 58 * will be returned.
michael@0 59 */
michael@0 60 template<typename T>
michael@0 61 T* createT() {
michael@0 62 void* buf = this->reserveT<T>();
michael@0 63 if (NULL == buf) {
michael@0 64 return NULL;
michael@0 65 }
michael@0 66 SkNEW_PLACEMENT(buf, T);
michael@0 67 return static_cast<T*>(buf);
michael@0 68 }
michael@0 69
michael@0 70 template<typename T, typename A1> T* createT(const A1& a1) {
michael@0 71 void* buf = this->reserveT<T>();
michael@0 72 if (NULL == buf) {
michael@0 73 return NULL;
michael@0 74 }
michael@0 75 SkNEW_PLACEMENT_ARGS(buf, T, (a1));
michael@0 76 return static_cast<T*>(buf);
michael@0 77 }
michael@0 78
michael@0 79 template<typename T, typename A1, typename A2>
michael@0 80 T* createT(const A1& a1, const A2& a2) {
michael@0 81 void* buf = this->reserveT<T>();
michael@0 82 if (NULL == buf) {
michael@0 83 return NULL;
michael@0 84 }
michael@0 85 SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2));
michael@0 86 return static_cast<T*>(buf);
michael@0 87 }
michael@0 88
michael@0 89 template<typename T, typename A1, typename A2, typename A3>
michael@0 90 T* createT(const A1& a1, const A2& a2, const A3& a3) {
michael@0 91 void* buf = this->reserveT<T>();
michael@0 92 if (NULL == buf) {
michael@0 93 return NULL;
michael@0 94 }
michael@0 95 SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3));
michael@0 96 return static_cast<T*>(buf);
michael@0 97 }
michael@0 98
michael@0 99 /*
michael@0 100 * Reserve a specified amount of space (must be enough space for one T).
michael@0 101 * The space will be in fStorage if there is room, or on the heap otherwise.
michael@0 102 * Either way, this class will call ~T() in its destructor and free the heap
michael@0 103 * allocation if necessary.
michael@0 104 * Unlike createT(), this method will not call the constructor of T.
michael@0 105 */
michael@0 106 template<typename T> void* reserveT(size_t storageRequired = sizeof(T)) {
michael@0 107 SkASSERT(fNumObjects < kMaxObjects);
michael@0 108 SkASSERT(storageRequired >= sizeof(T));
michael@0 109 if (kMaxObjects == fNumObjects) {
michael@0 110 return NULL;
michael@0 111 }
michael@0 112 const size_t storageRemaining = SkAlign4(kTotalBytes) - fStorageUsed;
michael@0 113 storageRequired = SkAlign4(storageRequired);
michael@0 114 Rec* rec = &fRecs[fNumObjects];
michael@0 115 if (storageRequired > storageRemaining) {
michael@0 116 // Allocate on the heap. Ideally we want to avoid this situation,
michael@0 117 // but we're not sure we can catch all callers, so handle it but
michael@0 118 // assert false in debug mode.
michael@0 119 SkASSERT(false);
michael@0 120 rec->fHeapStorage = sk_malloc_throw(storageRequired);
michael@0 121 rec->fObj = static_cast<void*>(rec->fHeapStorage);
michael@0 122 } else {
michael@0 123 // There is space in fStorage.
michael@0 124 rec->fHeapStorage = NULL;
michael@0 125 SkASSERT(SkIsAlign4(fStorageUsed));
michael@0 126 rec->fObj = static_cast<void*>(fStorage + (fStorageUsed / 4));
michael@0 127 fStorageUsed += storageRequired;
michael@0 128 }
michael@0 129 rec->fKillProc = destroyT<T>;
michael@0 130 fNumObjects++;
michael@0 131 return rec->fObj;
michael@0 132 }
michael@0 133
michael@0 134 private:
michael@0 135 struct Rec {
michael@0 136 void* fObj;
michael@0 137 void* fHeapStorage;
michael@0 138 void (*fKillProc)(void*);
michael@0 139 };
michael@0 140
michael@0 141 // Number of bytes used so far.
michael@0 142 size_t fStorageUsed;
michael@0 143 // Pad the storage size to be 4-byte aligned.
michael@0 144 uint32_t fStorage[SkAlign4(kTotalBytes) >> 2];
michael@0 145 uint32_t fNumObjects;
michael@0 146 Rec fRecs[kMaxObjects];
michael@0 147 };
michael@0 148
michael@0 149 #endif // SkSmallAllocator_DEFINED

mercurial