diff options
author | tsepez <tsepez@chromium.org> | 2016-10-17 11:20:01 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-10-17 11:20:01 -0700 |
commit | 2239cee23e914b974b458699d52733d7dd3116a6 (patch) | |
tree | c9c2baa2331b4ee4fc081dc09da27017ab718b2f /core/fxcrt/cfx_shared_copy_on_write.h | |
parent | d5bd8a16565bbee05bfb8a8409f3ba90c461da0e (diff) | |
download | pdfium-2239cee23e914b974b458699d52733d7dd3116a6.tar.xz |
Rename CFX_CountRef to CFX_SharedCopyOnWrite
Avoid confusing this class with other ref-counted objects.
Review-Url: https://codereview.chromium.org/2426673002
Diffstat (limited to 'core/fxcrt/cfx_shared_copy_on_write.h')
-rw-r--r-- | core/fxcrt/cfx_shared_copy_on_write.h | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/core/fxcrt/cfx_shared_copy_on_write.h b/core/fxcrt/cfx_shared_copy_on_write.h new file mode 100644 index 0000000000..cd6cf6adc5 --- /dev/null +++ b/core/fxcrt/cfx_shared_copy_on_write.h @@ -0,0 +1,84 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_SHARED_COPY_ON_WRITE_H_ +#define CORE_FXCRT_CFX_SHARED_COPY_ON_WRITE_H_ + +#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/fx_system.h" + +// A shared object with Copy on Write semantics that makes it appear as +// if each one were independent. +template <class ObjClass> +class CFX_SharedCopyOnWrite { + public: + CFX_SharedCopyOnWrite() {} + CFX_SharedCopyOnWrite(const CFX_SharedCopyOnWrite& other) + : m_pObject(other.m_pObject) {} + ~CFX_SharedCopyOnWrite() {} + + template <typename... Args> + ObjClass* Emplace(Args... params) { + m_pObject.Reset(new CountedObj(params...)); + return m_pObject.Get(); + } + + CFX_SharedCopyOnWrite& operator=(const CFX_SharedCopyOnWrite& that) { + if (*this != that) + m_pObject = that.m_pObject; + return *this; + } + + void SetNull() { m_pObject.Reset(); } + const ObjClass* GetObject() const { return m_pObject.Get(); } + + template <typename... Args> + ObjClass* GetPrivateCopy(Args... params) { + if (!m_pObject) + return Emplace(params...); + if (!m_pObject->HasOneRef()) + m_pObject.Reset(new CountedObj(*m_pObject)); + return m_pObject.Get(); + } + + bool operator==(const CFX_SharedCopyOnWrite& that) const { + return m_pObject == that.m_pObject; + } + bool operator!=(const CFX_SharedCopyOnWrite& that) const { + return !(*this == that); + } + explicit operator bool() const { return !!m_pObject; } + + private: + class CountedObj : public ObjClass { + public: + template <typename... Args> + CountedObj(Args... params) : ObjClass(params...), m_RefCount(0) {} + + CountedObj(const CountedObj& src) : ObjClass(src), m_RefCount(0) {} + ~CountedObj() { m_RefCount = 0; } + + bool HasOneRef() const { return m_RefCount == 1; } + void Retain() { m_RefCount++; } + void Release() { + ASSERT(m_RefCount); + if (--m_RefCount == 0) + delete this; + } + + private: + // To ensure ref counts do not overflow, consider the worst possible case: + // the entire address space contains nothing but pointers to this object. + // Since the count increments with each new pointer, the largest value is + // the number of pointers that can fit into the address space. The size of + // the address space itself is a good upper bound on it. + intptr_t m_RefCount; + }; + + CFX_RetainPtr<CountedObj> m_pObject; +}; + +#endif // CORE_FXCRT_CFX_SHARED_COPY_ON_WRITE_H_ |