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 
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 
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
Definition: i_ref_countable.h:61
Definition: ptr.h:18
static const InterfaceId * makeIdForTemplate(const char(&baseIdCharArray)[len])
Definition: i_ref_countable.h:103
virtual int releaseRef() const =0
virtual ~IRefCountable()=default
int refCountThreadUnsafe() const
Definition: i_ref_countable.h:165
Definition: apple_utils.h:6
static auto interfaceId()
Definition: i_ref_countable.h:87
virtual int addRef() const =0
Definition: i_ref_countable.h:49
static constexpr const InterfaceId * makeId(const char(&charArray)[len])
Definition: i_ref_countable.h:77