| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 PDFium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| 6 | |
| 7 #ifndef CORE_FXCRT_CFX_COUNT_REF_H_ | |
| 8 #define CORE_FXCRT_CFX_COUNT_REF_H_ | |
| 9 | |
| 10 #include "core/fxcrt/cfx_retain_ptr.h" | |
| 11 #include "core/fxcrt/fx_system.h" | |
| 12 | |
| 13 // A shared object with Copy on Write semantics that makes it appear as | |
| 14 // if each one were independent. | |
| 15 template <class ObjClass> | |
| 16 class CFX_CountRef { | |
| 17 public: | |
| 18 CFX_CountRef() {} | |
| 19 CFX_CountRef(const CFX_CountRef& other) : m_pObject(other.m_pObject) {} | |
| 20 ~CFX_CountRef() {} | |
| 21 | |
| 22 template <typename... Args> | |
| 23 ObjClass* Emplace(Args... params) { | |
| 24 m_pObject.Reset(new CountedObj(params...)); | |
| 25 return m_pObject.Get(); | |
| 26 } | |
| 27 | |
| 28 CFX_CountRef& operator=(const CFX_CountRef& that) { | |
| 29 if (*this != that) | |
| 30 m_pObject = that.m_pObject; | |
| 31 return *this; | |
| 32 } | |
| 33 | |
| 34 void SetNull() { m_pObject.Reset(); } | |
| 35 const ObjClass* GetObject() const { return m_pObject.Get(); } | |
| 36 | |
| 37 template <typename... Args> | |
| 38 ObjClass* GetPrivateCopy(Args... params) { | |
| 39 if (!m_pObject) | |
| 40 return Emplace(params...); | |
| 41 if (!m_pObject->HasOneRef()) | |
| 42 m_pObject.Reset(new CountedObj(*m_pObject)); | |
| 43 return m_pObject.Get(); | |
| 44 } | |
| 45 | |
| 46 bool operator==(const CFX_CountRef& that) const { | |
| 47 return m_pObject == that.m_pObject; | |
| 48 } | |
| 49 bool operator!=(const CFX_CountRef& that) const { return !(*this == that); } | |
| 50 explicit operator bool() const { return !!m_pObject; } | |
| 51 | |
| 52 private: | |
| 53 class CountedObj : public ObjClass { | |
| 54 public: | |
| 55 template <typename... Args> | |
| 56 CountedObj(Args... params) : ObjClass(params...), m_RefCount(0) {} | |
| 57 | |
| 58 CountedObj(const CountedObj& src) : ObjClass(src), m_RefCount(0) {} | |
| 59 ~CountedObj() { m_RefCount = 0; } | |
| 60 | |
| 61 bool HasOneRef() const { return m_RefCount == 1; } | |
| 62 void Retain() { m_RefCount++; } | |
| 63 void Release() { | |
| 64 ASSERT(m_RefCount); | |
| 65 if (--m_RefCount == 0) | |
| 66 delete this; | |
| 67 } | |
| 68 | |
| 69 private: | |
| 70 // To ensure ref counts do not overflow, consider the worst possible case: | |
| 71 // the entire address space contains nothing but pointers to this object. | |
| 72 // Since the count increments with each new pointer, the largest value is | |
| 73 // the number of pointers that can fit into the address space. The size of | |
| 74 // the address space itself is a good upper bound on it. | |
| 75 intptr_t m_RefCount; | |
| 76 }; | |
| 77 | |
| 78 CFX_RetainPtr<CountedObj> m_pObject; | |
| 79 }; | |
| 80 | |
| 81 #endif // CORE_FXCRT_CFX_COUNT_REF_H_ | |
| OLD | NEW |