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 |