• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SHARED_COPY_ON_WRITE_H_
8 #define CORE_FXCRT_CFX_SHARED_COPY_ON_WRITE_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_SharedCopyOnWrite {
17  public:
CFX_SharedCopyOnWrite()18   CFX_SharedCopyOnWrite() {}
CFX_SharedCopyOnWrite(const CFX_SharedCopyOnWrite & other)19   CFX_SharedCopyOnWrite(const CFX_SharedCopyOnWrite& other)
20       : m_pObject(other.m_pObject) {}
~CFX_SharedCopyOnWrite()21   ~CFX_SharedCopyOnWrite() {}
22 
23   template <typename... Args>
Emplace(Args...params)24   ObjClass* Emplace(Args... params) {
25     m_pObject.Reset(new CountedObj(params...));
26     return m_pObject.Get();
27   }
28 
29   CFX_SharedCopyOnWrite& operator=(const CFX_SharedCopyOnWrite& that) {
30     if (*this != that)
31       m_pObject = that.m_pObject;
32     return *this;
33   }
34 
SetNull()35   void SetNull() { m_pObject.Reset(); }
GetObject()36   const ObjClass* GetObject() const { return m_pObject.Get(); }
37 
38   template <typename... Args>
GetPrivateCopy(Args...params)39   ObjClass* GetPrivateCopy(Args... params) {
40     if (!m_pObject)
41       return Emplace(params...);
42     if (!m_pObject->HasOneRef())
43       m_pObject.Reset(new CountedObj(*m_pObject));
44     return m_pObject.Get();
45   }
46 
47   bool operator==(const CFX_SharedCopyOnWrite& that) const {
48     return m_pObject == that.m_pObject;
49   }
50   bool operator!=(const CFX_SharedCopyOnWrite& that) const {
51     return !(*this == that);
52   }
53   explicit operator bool() const { return !!m_pObject; }
54 
55  private:
56   class CountedObj : public ObjClass {
57    public:
58     template <typename... Args>
59     // NOLINTNEXTLINE(runtime/explicit)
CountedObj(Args...params)60     CountedObj(Args... params) : ObjClass(params...), m_RefCount(0) {}
61 
CountedObj(const CountedObj & src)62     CountedObj(const CountedObj& src) : ObjClass(src), m_RefCount(0) {}
~CountedObj()63     ~CountedObj() { m_RefCount = 0; }
64 
HasOneRef()65     bool HasOneRef() const { return m_RefCount == 1; }
Retain()66     void Retain() { m_RefCount++; }
Release()67     void Release() {
68       ASSERT(m_RefCount);
69       if (--m_RefCount == 0)
70         delete this;
71     }
72 
73    private:
74     // To ensure ref counts do not overflow, consider the worst possible case:
75     // the entire address space contains nothing but pointers to this object.
76     // Since the count increments with each new pointer, the largest value is
77     // the number of pointers that can fit into the address space. The size of
78     // the address space itself is a good upper bound on it.
79     intptr_t m_RefCount;
80   };
81 
82   CFX_RetainPtr<CountedObj> m_pObject;
83 };
84 
85 #endif  // CORE_FXCRT_CFX_SHARED_COPY_ON_WRITE_H_
86