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 
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 
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
Definition: i_ref_countable.h:61
Definition: ptr.h:18
static const InterfaceId * makeIdForTemplate(const char(&baseIdCharArray)[len])
Definition: i_ref_countable.h:120
virtual int releaseRef() const =0
virtual ~IRefCountable()=default
int refCountThreadUnsafe() const
Definition: i_ref_countable.h:197
static auto interfaceId()
Definition: i_ref_countable.h:103
Definition: device_agent.h:13
virtual int addRef() const =0
Definition: i_ref_countable.h:49
static std::vector< const InterfaceId * > makeIdWithAlternative(const char(&charArray)[len], const char(&alternativeCharArray)[alternativeLen])
Definition: i_ref_countable.h:87
static const InterfaceId * makeId(const char(&charArray)[len])
Definition: i_ref_countable.h:77