aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nswasabi/ReferenceCounted.h
diff options
context:
space:
mode:
Diffstat (limited to 'Src/replicant/nswasabi/ReferenceCounted.h')
-rw-r--r--Src/replicant/nswasabi/ReferenceCounted.h232
1 files changed, 232 insertions, 0 deletions
diff --git a/Src/replicant/nswasabi/ReferenceCounted.h b/Src/replicant/nswasabi/ReferenceCounted.h
new file mode 100644
index 00000000..c16b85dc
--- /dev/null
+++ b/Src/replicant/nswasabi/ReferenceCounted.h
@@ -0,0 +1,232 @@
+#pragma once
+#include "../foundation/dispatch.h"
+#include "../foundation/atomics.h"
+#include <new>
+#include "../nx/nxstring.h"
+#include "../nx/nxuri.h"
+
+#define REFERENCE_COUNT_AS(x) size_t Retain() { return x::Retain(); } size_t Release() { return x::Release(); }
+template <class t>
+class ReferenceCounted : public t
+{
+public:
+ ReferenceCounted() { reference_count = 1; }
+protected:
+ /* Dispatchable implementation */
+
+ size_t WASABICALL Dispatchable_Retain()
+ {
+ return nx_atomic_inc(&reference_count);
+ }
+
+ size_t WASABICALL Dispatchable_Release()
+ {
+ if (!reference_count)
+ return reference_count;
+ size_t r = nx_atomic_dec(&reference_count);
+ if (!r)
+ {
+#if defined(__ARM_ARCH_7A__)
+ __asm__ __volatile__ ("dmb" : : : "memory");
+#endif
+ delete(this);
+ }
+ return r;
+ }
+ size_t reference_count;
+};
+
+template <class t>
+class ReferenceCountedBase
+{
+public:
+ ReferenceCountedBase() { reference_count = 1; }
+
+ size_t Retain()
+ {
+ return nx_atomic_inc(&reference_count);
+ }
+
+ size_t Release()
+ {
+ if (!reference_count)
+ return reference_count;
+ size_t r = nx_atomic_dec(&reference_count);
+ if (!r)
+ {
+#if defined(__ARM_ARCH_7A__)
+ __asm__ __volatile__ ("dmb" : : : "memory");
+#endif
+ delete static_cast<t*>(this);
+ }
+ return r;
+ }
+ size_t reference_count;
+};
+
+template <class t>
+class ReferenceCountedObject
+{
+public:
+ ReferenceCountedObject()
+ {
+ ptr = new (std::nothrow) ReferenceCounted<t>;
+ };
+
+ ~ReferenceCountedObject()
+ {
+ if (ptr)
+ ptr->Release();
+ }
+
+ operator t *()
+ {
+ return ptr;
+ }
+
+ t *operator ->()
+ {
+ return ptr;
+ }
+
+ t *ptr;
+};
+
+template <class t>
+class ReferenceCountedPointer
+{
+public:
+ ReferenceCountedPointer()
+ {
+ ptr = 0;
+ };
+
+ ReferenceCountedPointer(t *new_ptr)
+ {
+ ptr = new_ptr;
+ };
+
+ ~ReferenceCountedPointer()
+ {
+ if (ptr)
+ ptr->Release();
+ }
+
+ operator t *()
+ {
+ return ptr;
+ }
+
+ t *operator ->()
+ {
+ return ptr;
+ }
+
+ t **operator &()
+ {
+ // if there's something already in here, we need to release it first
+ if (ptr)
+ ptr->Release();
+ ptr=0;
+ return &ptr;
+ }
+
+ t *operator =(t *new_ptr)
+ {
+ if (ptr)
+ ptr->Release();
+ ptr=0;
+ ptr = new_ptr;
+ return ptr;
+ }
+
+ t *ptr;
+};
+
+class ReferenceCountedNXString
+{
+public:
+ ReferenceCountedNXString()
+ {
+ ptr = 0;
+ }
+
+ ReferenceCountedNXString(const ReferenceCountedNXString &copy)
+ {
+ ptr = NXStringRetain(copy.ptr);
+ }
+
+ ~ReferenceCountedNXString()
+ {
+ NXStringRelease(ptr);
+ }
+
+ operator nx_string_t()
+ {
+ return ptr;
+ }
+
+ nx_string_t *operator &()
+ {
+ // if there's something already in here, we need to release it first
+ if (ptr)
+ NXStringRelease(ptr);
+ ptr=0;
+ return &ptr;
+ }
+
+ nx_string_t operator =(nx_string_t new_ptr)
+ {
+ if (ptr)
+ NXStringRelease(ptr);
+
+ ptr = new_ptr;
+ return ptr;
+ }
+
+ nx_string_t operator ->()
+ {
+ return ptr;
+ }
+
+ nx_string_t ptr;
+};
+
+class ReferenceCountedNXURI
+{
+public:
+ ReferenceCountedNXURI()
+ {
+ ptr = 0;
+ }
+
+ ReferenceCountedNXURI(const ReferenceCountedNXURI &copy)
+ {
+ ptr = NXURIRetain(copy.ptr);
+ }
+
+ ~ReferenceCountedNXURI()
+ {
+ NXURIRelease(ptr);
+ }
+
+ operator nx_uri_t()
+ {
+ return ptr;
+ }
+
+ nx_uri_t *operator &()
+ {
+ // if there's something already in here, we need to release it first
+ if (ptr)
+ NXURIRelease(ptr);
+ ptr=0;
+ return &ptr;
+ }
+
+ nx_uri_t operator ->()
+ {
+ return ptr;
+ }
+ nx_uri_t ptr;
+};