Sat, 03 Jan 2015 20:18:00 +0100
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 | /* |
michael@0 | 3 | * Copyright 2006 The Android Open Source Project |
michael@0 | 4 | * |
michael@0 | 5 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 6 | * found in the LICENSE file. |
michael@0 | 7 | */ |
michael@0 | 8 | |
michael@0 | 9 | |
michael@0 | 10 | #ifndef SkRefCnt_DEFINED |
michael@0 | 11 | #define SkRefCnt_DEFINED |
michael@0 | 12 | |
michael@0 | 13 | #include "SkDynamicAnnotations.h" |
michael@0 | 14 | #include "SkThread.h" |
michael@0 | 15 | #include "SkInstCnt.h" |
michael@0 | 16 | #include "SkTemplates.h" |
michael@0 | 17 | |
michael@0 | 18 | /** \class SkRefCntBase |
michael@0 | 19 | |
michael@0 | 20 | SkRefCntBase is the base class for objects that may be shared by multiple |
michael@0 | 21 | objects. When an existing owner wants to share a reference, it calls ref(). |
michael@0 | 22 | When an owner wants to release its reference, it calls unref(). When the |
michael@0 | 23 | shared object's reference count goes to zero as the result of an unref() |
michael@0 | 24 | call, its (virtual) destructor is called. It is an error for the |
michael@0 | 25 | destructor to be called explicitly (or via the object going out of scope on |
michael@0 | 26 | the stack or calling delete) if getRefCnt() > 1. |
michael@0 | 27 | */ |
michael@0 | 28 | class SK_API SkRefCntBase : public SkNoncopyable { |
michael@0 | 29 | public: |
michael@0 | 30 | SK_DECLARE_INST_COUNT_ROOT(SkRefCntBase) |
michael@0 | 31 | |
michael@0 | 32 | /** Default construct, initializing the reference count to 1. |
michael@0 | 33 | */ |
michael@0 | 34 | SkRefCntBase() : fRefCnt(1) {} |
michael@0 | 35 | |
michael@0 | 36 | /** Destruct, asserting that the reference count is 1. |
michael@0 | 37 | */ |
michael@0 | 38 | virtual ~SkRefCntBase() { |
michael@0 | 39 | #ifdef SK_DEBUG |
michael@0 | 40 | SkASSERT(fRefCnt == 1); |
michael@0 | 41 | fRefCnt = 0; // illegal value, to catch us if we reuse after delete |
michael@0 | 42 | #endif |
michael@0 | 43 | } |
michael@0 | 44 | |
michael@0 | 45 | /** Return the reference count. Use only for debugging. */ |
michael@0 | 46 | int32_t getRefCnt() const { return fRefCnt; } |
michael@0 | 47 | |
michael@0 | 48 | /** May return true if the caller is the only owner. |
michael@0 | 49 | * Ensures that all previous owner's actions are complete. |
michael@0 | 50 | */ |
michael@0 | 51 | bool unique() const { |
michael@0 | 52 | // We believe we're reading fRefCnt in a safe way here, so we stifle the TSAN warning about |
michael@0 | 53 | // an unproctected read. Generally, don't read fRefCnt, and don't stifle this warning. |
michael@0 | 54 | bool const unique = (1 == SK_ANNOTATE_UNPROTECTED_READ(fRefCnt)); |
michael@0 | 55 | if (unique) { |
michael@0 | 56 | // Acquire barrier (L/SL), if not provided by load of fRefCnt. |
michael@0 | 57 | // Prevents user's 'unique' code from happening before decrements. |
michael@0 | 58 | //TODO: issue the barrier. |
michael@0 | 59 | } |
michael@0 | 60 | return unique; |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | /** Increment the reference count. Must be balanced by a call to unref(). |
michael@0 | 64 | */ |
michael@0 | 65 | void ref() const { |
michael@0 | 66 | SkASSERT(fRefCnt > 0); |
michael@0 | 67 | sk_atomic_inc(&fRefCnt); // No barrier required. |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | /** Decrement the reference count. If the reference count is 1 before the |
michael@0 | 71 | decrement, then delete the object. Note that if this is the case, then |
michael@0 | 72 | the object needs to have been allocated via new, and not on the stack. |
michael@0 | 73 | */ |
michael@0 | 74 | void unref() const { |
michael@0 | 75 | SkASSERT(fRefCnt > 0); |
michael@0 | 76 | // Release barrier (SL/S), if not provided below. |
michael@0 | 77 | if (sk_atomic_dec(&fRefCnt) == 1) { |
michael@0 | 78 | // Acquire barrier (L/SL), if not provided above. |
michael@0 | 79 | // Prevents code in dispose from happening before the decrement. |
michael@0 | 80 | sk_membar_acquire__after_atomic_dec(); |
michael@0 | 81 | internal_dispose(); |
michael@0 | 82 | } |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | #ifdef SK_DEBUG |
michael@0 | 86 | void validate() const { |
michael@0 | 87 | SkASSERT(fRefCnt > 0); |
michael@0 | 88 | } |
michael@0 | 89 | #endif |
michael@0 | 90 | |
michael@0 | 91 | protected: |
michael@0 | 92 | /** |
michael@0 | 93 | * Allow subclasses to call this if they've overridden internal_dispose |
michael@0 | 94 | * so they can reset fRefCnt before the destructor is called. Should only |
michael@0 | 95 | * be called right before calling through to inherited internal_dispose() |
michael@0 | 96 | * or before calling the destructor. |
michael@0 | 97 | */ |
michael@0 | 98 | void internal_dispose_restore_refcnt_to_1() const { |
michael@0 | 99 | #ifdef SK_DEBUG |
michael@0 | 100 | SkASSERT(0 == fRefCnt); |
michael@0 | 101 | fRefCnt = 1; |
michael@0 | 102 | #endif |
michael@0 | 103 | } |
michael@0 | 104 | |
michael@0 | 105 | private: |
michael@0 | 106 | /** |
michael@0 | 107 | * Called when the ref count goes to 0. |
michael@0 | 108 | */ |
michael@0 | 109 | virtual void internal_dispose() const { |
michael@0 | 110 | this->internal_dispose_restore_refcnt_to_1(); |
michael@0 | 111 | SkDELETE(this); |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | // The following friends are those which override internal_dispose() |
michael@0 | 115 | // and conditionally call SkRefCnt::internal_dispose(). |
michael@0 | 116 | friend class GrTexture; |
michael@0 | 117 | friend class SkWeakRefCnt; |
michael@0 | 118 | |
michael@0 | 119 | mutable int32_t fRefCnt; |
michael@0 | 120 | |
michael@0 | 121 | typedef SkNoncopyable INHERITED; |
michael@0 | 122 | }; |
michael@0 | 123 | |
michael@0 | 124 | #ifdef SK_REF_CNT_MIXIN_INCLUDE |
michael@0 | 125 | // It is the responsibility of the following include to define the type SkRefCnt. |
michael@0 | 126 | // This SkRefCnt should normally derive from SkRefCntBase. |
michael@0 | 127 | #include SK_REF_CNT_MIXIN_INCLUDE |
michael@0 | 128 | #else |
michael@0 | 129 | class SK_API SkRefCnt : public SkRefCntBase { }; |
michael@0 | 130 | #endif |
michael@0 | 131 | |
michael@0 | 132 | /////////////////////////////////////////////////////////////////////////////// |
michael@0 | 133 | |
michael@0 | 134 | /** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for |
michael@0 | 135 | null in on each side of the assignment, and ensuring that ref() is called |
michael@0 | 136 | before unref(), in case the two pointers point to the same object. |
michael@0 | 137 | */ |
michael@0 | 138 | #define SkRefCnt_SafeAssign(dst, src) \ |
michael@0 | 139 | do { \ |
michael@0 | 140 | if (src) src->ref(); \ |
michael@0 | 141 | if (dst) dst->unref(); \ |
michael@0 | 142 | dst = src; \ |
michael@0 | 143 | } while (0) |
michael@0 | 144 | |
michael@0 | 145 | |
michael@0 | 146 | /** Call obj->ref() and return obj. The obj must not be NULL. |
michael@0 | 147 | */ |
michael@0 | 148 | template <typename T> static inline T* SkRef(T* obj) { |
michael@0 | 149 | SkASSERT(obj); |
michael@0 | 150 | obj->ref(); |
michael@0 | 151 | return obj; |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | /** Check if the argument is non-null, and if so, call obj->ref() and return obj. |
michael@0 | 155 | */ |
michael@0 | 156 | template <typename T> static inline T* SkSafeRef(T* obj) { |
michael@0 | 157 | if (obj) { |
michael@0 | 158 | obj->ref(); |
michael@0 | 159 | } |
michael@0 | 160 | return obj; |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | /** Check if the argument is non-null, and if so, call obj->unref() |
michael@0 | 164 | */ |
michael@0 | 165 | template <typename T> static inline void SkSafeUnref(T* obj) { |
michael@0 | 166 | if (obj) { |
michael@0 | 167 | obj->unref(); |
michael@0 | 168 | } |
michael@0 | 169 | } |
michael@0 | 170 | |
michael@0 | 171 | template<typename T> static inline void SkSafeSetNull(T*& obj) { |
michael@0 | 172 | if (NULL != obj) { |
michael@0 | 173 | obj->unref(); |
michael@0 | 174 | obj = NULL; |
michael@0 | 175 | } |
michael@0 | 176 | } |
michael@0 | 177 | |
michael@0 | 178 | /////////////////////////////////////////////////////////////////////////////// |
michael@0 | 179 | |
michael@0 | 180 | /** |
michael@0 | 181 | * Utility class that simply unref's its argument in the destructor. |
michael@0 | 182 | */ |
michael@0 | 183 | template <typename T> class SkAutoTUnref : SkNoncopyable { |
michael@0 | 184 | public: |
michael@0 | 185 | explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {} |
michael@0 | 186 | ~SkAutoTUnref() { SkSafeUnref(fObj); } |
michael@0 | 187 | |
michael@0 | 188 | T* get() const { return fObj; } |
michael@0 | 189 | |
michael@0 | 190 | T* reset(T* obj) { |
michael@0 | 191 | SkSafeUnref(fObj); |
michael@0 | 192 | fObj = obj; |
michael@0 | 193 | return obj; |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | void swap(SkAutoTUnref* other) { |
michael@0 | 197 | T* tmp = fObj; |
michael@0 | 198 | fObj = other->fObj; |
michael@0 | 199 | other->fObj = tmp; |
michael@0 | 200 | } |
michael@0 | 201 | |
michael@0 | 202 | /** |
michael@0 | 203 | * Return the hosted object (which may be null), transferring ownership. |
michael@0 | 204 | * The reference count is not modified, and the internal ptr is set to NULL |
michael@0 | 205 | * so unref() will not be called in our destructor. A subsequent call to |
michael@0 | 206 | * detach() will do nothing and return null. |
michael@0 | 207 | */ |
michael@0 | 208 | T* detach() { |
michael@0 | 209 | T* obj = fObj; |
michael@0 | 210 | fObj = NULL; |
michael@0 | 211 | return obj; |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | /** |
michael@0 | 215 | * BlockRef<B> is a type which inherits from B, cannot be created, |
michael@0 | 216 | * cannot be deleted, and makes ref and unref private. |
michael@0 | 217 | */ |
michael@0 | 218 | template<typename B> class BlockRef : public B { |
michael@0 | 219 | private: |
michael@0 | 220 | BlockRef(); |
michael@0 | 221 | ~BlockRef(); |
michael@0 | 222 | void ref() const; |
michael@0 | 223 | void unref() const; |
michael@0 | 224 | }; |
michael@0 | 225 | |
michael@0 | 226 | /** If T is const, the type returned from operator-> will also be const. */ |
michael@0 | 227 | typedef typename SkTConstType<BlockRef<T>, SkTIsConst<T>::value>::type BlockRefType; |
michael@0 | 228 | |
michael@0 | 229 | /** |
michael@0 | 230 | * SkAutoTUnref assumes ownership of the ref. As a result, it is an error |
michael@0 | 231 | * for the user to ref or unref through SkAutoTUnref. Therefore |
michael@0 | 232 | * SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of |
michael@0 | 233 | * skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref(). |
michael@0 | 234 | */ |
michael@0 | 235 | BlockRefType *operator->() const { |
michael@0 | 236 | return static_cast<BlockRefType*>(fObj); |
michael@0 | 237 | } |
michael@0 | 238 | operator T*() { return fObj; } |
michael@0 | 239 | |
michael@0 | 240 | private: |
michael@0 | 241 | T* fObj; |
michael@0 | 242 | }; |
michael@0 | 243 | // Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :( |
michael@0 | 244 | |
michael@0 | 245 | class SkAutoUnref : public SkAutoTUnref<SkRefCnt> { |
michael@0 | 246 | public: |
michael@0 | 247 | SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} |
michael@0 | 248 | }; |
michael@0 | 249 | #define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) |
michael@0 | 250 | |
michael@0 | 251 | class SkAutoRef : SkNoncopyable { |
michael@0 | 252 | public: |
michael@0 | 253 | SkAutoRef(SkRefCnt* obj) : fObj(obj) { SkSafeRef(obj); } |
michael@0 | 254 | ~SkAutoRef() { SkSafeUnref(fObj); } |
michael@0 | 255 | private: |
michael@0 | 256 | SkRefCnt* fObj; |
michael@0 | 257 | }; |
michael@0 | 258 | #define SkAutoRef(...) SK_REQUIRE_LOCAL_VAR(SkAutoRef) |
michael@0 | 259 | |
michael@0 | 260 | /** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to |
michael@0 | 261 | a SkRefCnt (or subclass) object. |
michael@0 | 262 | */ |
michael@0 | 263 | template <typename T> class SkRefPtr { |
michael@0 | 264 | public: |
michael@0 | 265 | SkRefPtr() : fObj(NULL) {} |
michael@0 | 266 | SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); } |
michael@0 | 267 | SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); } |
michael@0 | 268 | ~SkRefPtr() { SkSafeUnref(fObj); } |
michael@0 | 269 | |
michael@0 | 270 | SkRefPtr& operator=(const SkRefPtr& rp) { |
michael@0 | 271 | SkRefCnt_SafeAssign(fObj, rp.fObj); |
michael@0 | 272 | return *this; |
michael@0 | 273 | } |
michael@0 | 274 | SkRefPtr& operator=(T* obj) { |
michael@0 | 275 | SkRefCnt_SafeAssign(fObj, obj); |
michael@0 | 276 | return *this; |
michael@0 | 277 | } |
michael@0 | 278 | |
michael@0 | 279 | T* get() const { return fObj; } |
michael@0 | 280 | T& operator*() const { return *fObj; } |
michael@0 | 281 | T* operator->() const { return fObj; } |
michael@0 | 282 | |
michael@0 | 283 | typedef T* SkRefPtr::*unspecified_bool_type; |
michael@0 | 284 | operator unspecified_bool_type() const { |
michael@0 | 285 | return fObj ? &SkRefPtr::fObj : NULL; |
michael@0 | 286 | } |
michael@0 | 287 | |
michael@0 | 288 | private: |
michael@0 | 289 | T* fObj; |
michael@0 | 290 | }; |
michael@0 | 291 | |
michael@0 | 292 | #endif |