nx_metadata_sdk 1.0 Metadata SDK

i_ref_countable.h
1 // Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/
2
3 #pragma once
4
5 #include <cstring>
6 #include <string>
7 #include <type_traits>
8
9 #include <nx/sdk/ptr.h>
10
11 namespace nx {
12 namespace sdk {
13
49 class IRefCountable
50 {
51 public:
61 struct InterfaceId
62 {
63 static constexpr int kMinSize = 16; //< For compatibility with the old SDK.
64 static constexpr int minSize() { return kMinSize; } //< For C++14, to avoid the definition.
65
66 char value[kMinSize];
67
68 InterfaceId() = delete; //< No instances - only InterfaceId* are used via reinterpret_cast.
69
70 bool operator==(const InterfaceId& other) const { return strcmp(value, other.value) == 0; }
71 bool operator!=(const InterfaceId& other) const { return !(*this == other); }
72 };
73
74 protected:
76 template<int len>
77 static constexpr const InterfaceId* makeId(const char (&charArray)[len])
78 {
79 static_assert(len + /*terminating \0*/ 1 >= InterfaceId::minSize(),
80 "Interface id is too short");
81
82 return reinterpret_cast<const InterfaceId*>(charArray);
83 }
84
85 public:
87 static auto interfaceId() { return makeId("nx::sdk::IRefCountable"); }
88
90 virtual ~IRefCountable() = default;
91
92 protected:
102 template<class TemplateInstance, class TemplateArg, int len>
103 static const InterfaceId* makeIdForTemplate(const char (&baseIdCharArray)[len])
104 {
105 static_assert(len + /*angle brackets*/ 2 + /*terminating \0*/ 1 >= InterfaceId::minSize(),
106 "Base part of interface id is too short");
107 static_assert(std::is_base_of<IRefCountable, TemplateInstance>::value,
108 "TemplateInstance must be inherited from IRefCountable");
109 static_assert(std::is_base_of<IRefCountable, TemplateArg>::value,
110 "TemplateArg must be inherited from IRefCountable");
111
112 static const std::string id =
113 std::string(&baseIdCharArray[0]) + "<" + &TemplateArg::interfaceId()->value[0] + ">";
114
115 return reinterpret_cast<const InterfaceId*>(id.c_str());
116 }
117
125 virtual IRefCountable* queryInterface(const InterfaceId* id)
126 {
127 if (*interfaceId() == *id)
128 {
129 addRef();
130 return this;
131 }
132 return nullptr;
133 }
134
135 public:
136 template<class Interface>
137 Ptr<Interface> queryInterface()
138 {
139 return toPtr(static_cast<Interface*>(queryInterface(Interface::interfaceId())));
140 }
141
142 template<class Interface>
143 Ptr<const Interface> queryInterface() const
144 {
145 return toPtr(static_cast<const Interface*>(
146 const_cast<IRefCountable*>(this)->queryInterface(Interface::interfaceId())));
147 }
148
153 virtual int addRef() const = 0;
154
159 virtual int releaseRef() const = 0;
160
165 int refCountThreadUnsafe() const
166 {
167 const void* this_ = this; //< Suppress warning that `this` cannot be null.
168 if (this_ == nullptr)
169 return 0;
170
171 /*unused*/ (void) addRef();
172 return releaseRef();
173 }
174 };
175
176 } // namespace sdk
177 } // namespace nx
nx::sdk::IRefCountable::InterfaceId
Definition: i_ref_countable.h:61
nx::sdk::Ptr
Definition: ptr.h:18
nx::sdk::IRefCountable::makeIdForTemplate
static const InterfaceId * makeIdForTemplate(const char(&baseIdCharArray)[len])
Definition: i_ref_countable.h:103
nx::sdk::IRefCountable::releaseRef
virtual int releaseRef() const =0
nx::sdk::IRefCountable::~IRefCountable
virtual ~IRefCountable()=default
nx::sdk::IRefCountable::refCountThreadUnsafe
int refCountThreadUnsafe() const
Definition: i_ref_countable.h:165
nx
Definition: apple_utils.h:6
nx::sdk::IRefCountable::interfaceId
static auto interfaceId()
Definition: i_ref_countable.h:87
nx::sdk::IRefCountable::addRef
virtual int addRef() const =0
nx::sdk::IRefCountable
Definition: i_ref_countable.h:49
nx::sdk::IRefCountable::makeId
static constexpr const InterfaceId * makeId(const char(&charArray)[len])
Definition: i_ref_countable.h:77