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 
135  template<typename RefCountable>
137  {
138  private:
139  // SFINAE: The first overload will be chosen when T::alternativeInterfaceId() exists,
140  // the second overload will be chosen otherwise. Since test() is used only in decltype(),
141  // it does not need a function definition.
142 
143  template<typename T>
144  static constexpr std::true_type test(decltype(T::alternativeInterfaceId())* arg);
145 
146  template<typename T>
147  static constexpr std::false_type test(...);
148 
149  public:
150  static constexpr bool value = decltype(test<RefCountable>(nullptr))::value;
151  };
152 
160  template<typename RefCountable>
162 
163 public:
164  template<class RefCountable>
166  {
167  IRefCountable* refCountable = nullptr;
168  if constexpr (hasAlternativeInterfaceId<RefCountable>)
169  refCountable = queryInterface(RefCountable::alternativeInterfaceId());
170  if (!refCountable)
171  refCountable = queryInterface(RefCountable::interfaceId());
172  return Ptr(static_cast<RefCountable*>(refCountable));
173  }
174 
175  template<class RefCountable>
176  Ptr<const RefCountable> queryInterface() const
177  {
178  auto nonConstThis = const_cast<IRefCountable*>(this);
179  IRefCountable* refCountable = nullptr;
180  if constexpr (hasAlternativeInterfaceId<RefCountable>)
181  refCountable = nonConstThis->queryInterface(RefCountable::alternativeInterfaceId());
182  if (!refCountable)
183  refCountable = nonConstThis->queryInterface(RefCountable::interfaceId());
184  return Ptr(static_cast<const RefCountable*>(refCountable));
185  }
186 
191  virtual int addRef() const = 0;
192 
197  virtual int releaseRef() const = 0;
198 
204  {
205  const void* this_ = this; //< Suppress warning that `this` cannot be null.
206  if (this_ == nullptr)
207  return 0;
208 
209  /*unused*/ (void) addRef();
210  return releaseRef();
211  }
212 };
213 
214 } // namespace nx::sdk
Definition: i_ref_countable.h:60
static constexpr bool hasAlternativeInterfaceId
Definition: i_ref_countable.h:161
Definition: json_ut.cpp:14
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 * queryInterface(const InterfaceId *id)
Definition: i_ref_countable.h:124
virtual ~IRefCountable()=default
int refCountThreadUnsafe() const
Definition: i_ref_countable.h:203
static auto interfaceId()
Definition: i_ref_countable.h:86
Definition: device_agent.h:12
Definition: i_ref_countable.h:136
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