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 <cstdarg>
7 #include <cassert>
8 #include <type_traits>
9 
10 #include <nx/sdk/ptr.h>
11 
12 namespace nx {
13 namespace sdk {
14 
51 {
52 public:
62  struct InterfaceId
63  {
64  static constexpr int kMinSize = 16; //< For compatibility with the old SDK.
65  static constexpr int minSize() { return kMinSize; } //< For C++14, to avoid the definition.
66 
67  char value[kMinSize];
68 
69  InterfaceId() = delete; //< No instances - only InterfaceId* are used via reinterpret_cast.
70 
71  bool operator==(const InterfaceId& other) const { return strcmp(value, other.value) == 0; }
72  bool operator!=(const InterfaceId& other) const { return !(*this == other); }
73  };
74 
75 protected:
77  template<int len>
78  static constexpr const InterfaceId* makeId(const char (&charArray)[len])
79  {
80  static_assert(len + /*terminating zero*/ 1 >= InterfaceId::minSize(),
81  "Interface id is too short");
82 
83  return reinterpret_cast<const InterfaceId*>(charArray);
84  }
85 
86 public:
88  static auto interfaceId() { return makeId("nx::sdk::IRefCountable"); }
89 
91  virtual ~IRefCountable() = default;
92 
93 protected:
103  template<class TemplateInstance, class TemplateArg, int len>
104  static const InterfaceId* makeIdForTemplate(const char (&baseIdCharArray)[len])
105  {
106  static constexpr int kMaxStaticInterfaceIdSize = 256;
107 
108  static_assert(len >= 1, "baseIdCharArray should not be empty");
109  static_assert(std::is_base_of<IRefCountable, TemplateInstance>::value,
110  "TemplateInstance should be inherited from IRefCountable");
111  static_assert(std::is_base_of<IRefCountable, TemplateArg>::value,
112  "TemplateArg should be inherited from IRefCountable");
113 
114  // The id is stored in a static array because it is unique for the given template args.
115  static char id[kMaxStaticInterfaceIdSize];
116  assert(id[0] == '\0'); //< Assert that the static id has not been initialized yet.
117 
118  const int result = snprintf(
119  id,
120  kMaxStaticInterfaceIdSize,
121  "%s<%s>",
122  baseIdCharArray,
123  TemplateArg::interfaceId()->value);
124 
125  /*unused*/ (void) result; //< If assert() is wiped out in Release, `result` will be unused.
126  assert(result >= InterfaceId::minSize() - 1);
127  assert(result < kMaxStaticInterfaceIdSize);
128 
129  return reinterpret_cast<const InterfaceId*>(id);
130  }
131 
139  virtual IRefCountable* queryInterface(const InterfaceId* id)
140  {
141  if (*interfaceId() == *id)
142  {
143  addRef();
144  return this;
145  }
146  return nullptr;
147  }
148 
149 public:
150  template<class Interface>
151  Ptr<Interface> queryInterface()
152  {
153  return toPtr(static_cast<Interface*>(queryInterface(Interface::interfaceId())));
154  }
155 
156  template<class Interface>
157  Ptr<const Interface> queryInterface() const
158  {
159  return toPtr(static_cast<const Interface*>(
160  const_cast<IRefCountable*>(this)->queryInterface(Interface::interfaceId())));
161  }
162 
167  virtual int addRef() const = 0;
168 
173  virtual int releaseRef() const = 0;
174 
180  {
181  const void* this_ = this; //< Suppress warning that `this` cannot be null.
182  if (this_ == nullptr)
183  return 0;
184 
185  /*unused*/ (void) addRef();
186  return releaseRef();
187  }
188 };
189 
190 } // namespace sdk
191 } // namespace nx
Definition: i_ref_countable.h:62
Definition: ptr.h:18
static const InterfaceId * makeIdForTemplate(const char(&baseIdCharArray)[len])
Definition: i_ref_countable.h:104
virtual int releaseRef() const =0
virtual ~IRefCountable()=default
int refCountThreadUnsafe() const
Definition: i_ref_countable.h:179
Definition: apple_utils.h:6
static auto interfaceId()
Definition: i_ref_countable.h:88
virtual int addRef() const =0
Definition: i_ref_countable.h:50
static constexpr const InterfaceId * makeId(const char(&charArray)[len])
Definition: i_ref_countable.h:78