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::sdk {
12 
49 {
50 public:
60  struct InterfaceId
61  {
62  static constexpr int kMinSize = 16; //< For compatibility with the old SDK.
63  static constexpr int minSize() { return kMinSize; } //< For C++14, to avoid the definition.
64 
65  char value[kMinSize];
66 
67  InterfaceId() = delete; //< No instances - only InterfaceId* are used via reinterpret_cast.
68 
69  bool operator==(const InterfaceId& other) const { return strcmp(value, other.value) == 0; }
70  bool operator!=(const InterfaceId& other) const { return !(*this == other); }
71  };
72 
73 protected:
75  template<int len>
76  static constexpr const InterfaceId* makeId(const char (&charArray)[len])
77  {
78  static_assert(len + /*terminating \0*/ 1 >= InterfaceId::minSize(),
79  "Interface id is too short");
80 
81  return reinterpret_cast<const InterfaceId*>(charArray);
82  }
83 
84 public:
86  static auto interfaceId() { return makeId("nx::sdk::IRefCountable"); }
87 
89  virtual ~IRefCountable() = default;
90 
91 protected:
101  template<class TemplateInstance, class TemplateArg, int len>
102  static const InterfaceId* makeIdForTemplate(const char (&baseIdCharArray)[len])
103  {
104  static_assert(len + /*angle brackets*/ 2 + /*terminating \0*/ 1 >= InterfaceId::minSize(),
105  "Base part of interface id is too short");
106  static_assert(std::is_base_of<IRefCountable, TemplateInstance>::value,
107  "TemplateInstance must be inherited from IRefCountable");
108  static_assert(std::is_base_of<IRefCountable, TemplateArg>::value,
109  "TemplateArg must be inherited from IRefCountable");
110 
111  static const std::string id =
112  std::string(&baseIdCharArray[0]) + "<" + &TemplateArg::interfaceId()->value[0] + ">";
113 
114  return reinterpret_cast<const InterfaceId*>(id.c_str());
115  }
116 
124  virtual IRefCountable* queryInterface(const InterfaceId* id)
125  {
126  if (*interfaceId() == *id)
127  {
128  addRef();
129  return this;
130  }
131  return nullptr;
132  }
133 
134 public:
135  template<class Interface>
136  Ptr<Interface> queryInterface()
137  {
138  return Ptr(static_cast<Interface*>(queryInterface(Interface::interfaceId())));
139  }
140 
141  template<class Interface>
142  Ptr<const Interface> queryInterface() const
143  {
144  return Ptr(static_cast<const Interface*>(
145  const_cast<IRefCountable*>(this)->queryInterface(Interface::interfaceId())));
146  }
147 
152  virtual int addRef() const = 0;
153 
158  virtual int releaseRef() const = 0;
159 
165  {
166  const void* this_ = this; //< Suppress warning that `this` cannot be null.
167  if (this_ == nullptr)
168  return 0;
169 
170  /*unused*/ (void) addRef();
171  return releaseRef();
172  }
173 };
174 
175 } // namespace nx::sdk
Definition: i_ref_countable.h:60
Definition: ptr.h:18
static const InterfaceId * makeIdForTemplate(const char(&baseIdCharArray)[len])
Definition: i_ref_countable.h:102
virtual int releaseRef() const =0
virtual ~IRefCountable()=default
int refCountThreadUnsafe() const
Definition: i_ref_countable.h:164
static auto interfaceId()
Definition: i_ref_countable.h:86
Definition: device_agent.h:12
virtual int addRef() const =0
Definition: i_ref_countable.h:48
static constexpr const InterfaceId * makeId(const char(&charArray)[len])
Definition: i_ref_countable.h:76