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 <vector>
7 #include <string>
8 #include <type_traits>
9
10 #include <nx/sdk/ptr.h>
11
12 namespace nx::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 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
86 template<int len, int alternativeLen>
87 static std::vector<const InterfaceId*> makeIdWithAlternative(
88 const char (&charArray)[len], const char (&alternativeCharArray)[alternativeLen])
89 {
90 static_assert(len + /*terminating \0*/ 1 >= InterfaceId::minSize(),
91 "Interface id is too short");
92 static_assert(alternativeLen + /*terminating \0*/ 1 >= InterfaceId::minSize(),
93 "Alternative interface id is too short");
94
95 return {
96 reinterpret_cast<const InterfaceId*>(charArray),
97 reinterpret_cast<const InterfaceId*>(alternativeCharArray),
98 };
99 }
100
101 public:
103 static auto interfaceId() { return makeId("nx::sdk::IRefCountable"); }
104
106 virtual ~IRefCountable() = default;
107
108 protected:
119 template<class TemplateInstance, class TemplateArg, int len>
120 static const InterfaceId* makeIdForTemplate(const char (&baseIdCharArray)[len])
121 {
122 static_assert(len + /*angle brackets*/ 2 + /*terminating \0*/ 1 >= InterfaceId::minSize(),
123 "Base part of interface id is too short");
124 static_assert(std::is_base_of<IRefCountable, TemplateInstance>::value,
125 "TemplateInstance must be inherited from IRefCountable");
126 static_assert(std::is_base_of<IRefCountable, TemplateArg>::value,
127 "TemplateArg must be inherited from IRefCountable");
128
129 static const std::string id =
130 std::string(&baseIdCharArray[0]) + "<" + &TemplateArg::interfaceId()->value[0] + ">";
131
132 return reinterpret_cast<const InterfaceId*>(id.c_str());
133 }
134
135 static std::vector<const InterfaceId*> alternativeInterfaceIds(const InterfaceId* id)
136 {
137 return std::vector<const InterfaceId*>(1, id);
138 }
139
140 static std::vector<const InterfaceId*> alternativeInterfaceIds(std::vector<const InterfaceId*> ids)
141 {
142 return ids;
143 }
144
152 virtual IRefCountable* queryInterface(const InterfaceId* id)
153 {
154 if (*interfaceId() == *id)
155 {
156 addRef();
157 return this;
158 }
159 return nullptr;
160 }
161
162 public:
163 template<class Interface>
164 Ptr<Interface> queryInterface()
165 {
166 for (const auto& id: alternativeInterfaceIds(Interface::interfaceId()))
167 {
168 if (IRefCountable* refCountable = queryInterface(id))
169 return Ptr(static_cast<Interface*>(refCountable));
170 }
171 return nullptr;
172 }
173
174 template<class Interface>
175 Ptr<const Interface> queryInterface() const
176 {
177 // The virtual queryInterface() does not have a const overload.
178 return const_cast<IRefCountable*>(this)->queryInterface<const Interface>();
179 }
180
185 virtual int addRef() const = 0;
186
191 virtual int releaseRef() const = 0;
192
197 int refCountThreadUnsafe() const
198 {
199 const void* this_ = this; //< Suppress warning that `this` cannot be null.
200 if (this_ == nullptr)
201 return 0;
202
203 /*unused*/ (void) addRef();
204 return releaseRef();
205 }
206 };
207
208 } // namespace nx::sdk
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:120
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:197
nx::sdk::IRefCountable::interfaceId
static auto interfaceId()
Definition: i_ref_countable.h:103
nx::sdk
Definition: device_agent.h:12
nx::sdk::IRefCountable::addRef
virtual int addRef() const =0
nx::sdk::IRefCountable
Definition: i_ref_countable.h:49
nx::sdk::IRefCountable::makeIdWithAlternative
static std::vector< const InterfaceId * > makeIdWithAlternative(const char(&charArray)[len], const char(&alternativeCharArray)[alternativeLen])
Definition: i_ref_countable.h:87
nx::sdk::IRefCountable::makeId
static const InterfaceId * makeId(const char(&charArray)[len])
Definition: i_ref_countable.h:77