diff options
| author | Mason Reed <mason@vector35.com> | 2025-03-10 11:05:40 -0400 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-04-02 05:36:54 -0400 |
| commit | 25cc02431b61097b2adfc2fbc493b648b0300c3b (patch) | |
| tree | a79d9c4f4f67234d3bf9bda413e8608f479a4cc8 /view/sharedcache/core/refcountobject.h | |
| parent | fa85bf28502286c4821427c5d0ed91a7ed46f8f6 (diff) | |
[SharedCache] Refactor Shared Cache
In absence of a better name, this commit refactors the shared cache code.
Diffstat (limited to 'view/sharedcache/core/refcountobject.h')
| -rw-r--r-- | view/sharedcache/core/refcountobject.h | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/view/sharedcache/core/refcountobject.h b/view/sharedcache/core/refcountobject.h new file mode 100644 index 00000000..1b79f12f --- /dev/null +++ b/view/sharedcache/core/refcountobject.h @@ -0,0 +1,223 @@ +/* +Copyright 2020-2024 Vector 35 Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#pragma once + +#ifdef WIN32 + #include <windows.h> +#endif +#include <stddef.h> +#include <vector> +#include <atomic> + +namespace BinaryNinja::DSC { + class DSCRefCountObject + { + // CORE_ALLOCATED_CLASS(RefCountObject) + + public: + std::atomic<int> m_refs; + + DSCRefCountObject() : m_refs(0) {} + + virtual ~DSCRefCountObject() {} + + virtual void AddRef() { m_refs.fetch_add(1); } + + virtual void Release() + { + if (m_refs.fetch_sub(1) == 1) + delete this; + } + + virtual void AddAPIRef() { AddRef(); } + + virtual void ReleaseAPIRef() { Release(); } + }; + + + template <class T> + class DSCRef + { + T* m_obj; +#ifdef BN_REF_COUNT_DEBUG + void* m_assignmentTrace = nullptr; +#endif + + public: + DSCRef<T>() : m_obj(NULL) {} + + DSCRef<T>(T* obj) : m_obj(obj) + { + if (m_obj) + { + m_obj->AddRef(); +#ifdef BN_REF_COUNT_DEBUG + m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name()); +#endif + } + } + + DSCRef<T>(const DSCRef<T>& obj) : m_obj(obj.m_obj) + { + if (m_obj) + { + m_obj->AddRef(); +#ifdef BN_REF_COUNT_DEBUG + m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name()); +#endif + } + } + + ~DSCRef<T>() + { + if (m_obj) + { + m_obj->Release(); +#ifdef BN_REF_COUNT_DEBUG + BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace); +#endif + } + } + + // move constructor + DSCRef<T>(DSCRef<T>&& other) : m_obj(other.m_obj) + { + other.m_obj = 0; +#ifdef BN_REF_COUNT_DEBUG + m_assignmentTrace = other.m_assignmentTrace; +#endif + } + + // move assignment (inefficient in this case) + // Ref<T>& operator=(Ref<T>&& other) + // { + // if (m_obj) + // { + // #ifdef BN_REF_COUNT_DEBUG + // BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace); + // #endif + // m_obj->Release(); + // } + // m_obj = other.m_obj; + // other.m_obj = 0; + // #ifdef BN_REF_COUNT_DEBUG + // m_assignmentTrace = other.m_assignmentTrace; + // #endif + // return *this; + // } + + DSCRef<T>& operator=(const DSCRef<T>& obj) + { +#ifdef BN_REF_COUNT_DEBUG + if (m_obj) + BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace); + if (obj.m_obj) + m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name()); +#endif + T* oldObj = m_obj; + m_obj = obj.m_obj; + if (m_obj) + m_obj->AddRef(); + if (oldObj) + oldObj->Release(); + return *this; + } + + DSCRef<T>& operator=(T* obj) + { +#ifdef BN_REF_COUNT_DEBUG + if (m_obj) + BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace); + if (obj) + m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name()); +#endif + T* oldObj = m_obj; + m_obj = obj; + if (m_obj) + m_obj->AddRef(); + if (oldObj) + oldObj->Release(); + return *this; + } + + operator T*() const { return m_obj; } + + T* operator->() const { return m_obj; } + + T& operator*() const { return *m_obj; } + + bool operator!() const { return m_obj == NULL; } + + T* GetPtr() const { return m_obj; } + + bool operator==(const DSCRef<T>& obj) const { return m_obj == obj.m_obj; } + + bool operator!=(const DSCRef<T>& obj) const { return m_obj != obj.m_obj; } + + bool operator<(const DSCRef<T>& obj) const { return m_obj < obj.m_obj; } + + template <typename H> + friend H AbslHashValue(H h, const DSCRef<T>& value) + { + return AbslHashValue(std::move(h), value.m_obj); + } + }; + + + // Macro-like functions to manage referenced objects for the external API + template <class T> + static typename T::APIHandle DSC_API_OBJECT_REF(T* obj) + { + if (obj == nullptr) + return nullptr; + obj->AddAPIRef(); + return obj->GetAPIObject(); + } + + template <class T> + static typename T::APIHandle DSC_API_OBJECT_REF(const DSCRef<T>& obj) + { + if (!obj) + return nullptr; + obj->AddAPIRef(); + return obj->GetAPIObject(); + } + + // template <class T> + // static typename T::APIHandle DSC_API_OBJECT_REF(const APIRef<T>& obj) + //{ + // if (!obj) + // return nullptr; + // obj->AddAPIRef(); + // return obj->GetAPIObject(); + // } + + template <class T> + static T* DSC_API_OBJECT_NEW_REF(T* obj) + { + if (obj) + obj->object->AddAPIRef(); + return obj; + } + + template <class T> + static void DSC_API_OBJECT_FREE(T* obj) + { + if (obj) + obj->object->ReleaseAPIRef(); + } +}; // namespace BinaryNinja::DSC |
