summaryrefslogtreecommitdiff
path: root/view/sharedcache/core/refcountobject.h
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-03-10 11:05:40 -0400
committerMason Reed <mason@vector35.com>2025-04-02 05:36:54 -0400
commit25cc02431b61097b2adfc2fbc493b648b0300c3b (patch)
treea79d9c4f4f67234d3bf9bda413e8608f479a4cc8 /view/sharedcache/core/refcountobject.h
parentfa85bf28502286c4821427c5d0ed91a7ed46f8f6 (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.h223
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