ADTF  3.18.2
stack_ptr_impl.h
Go to the documentation of this file.
1 
15 #ifndef A_UTIL_UTIL_MEMORY_DETAIL_STACK_PTR_IMPL_HEADER_INCLUDED
16 #define A_UTIL_UTIL_MEMORY_DETAIL_STACK_PTR_IMPL_HEADER_INCLUDED
17 
19 #include <new>
20 
21 namespace a_util {
22 namespace memory {
23 
24 template <typename T, std::size_t StackSize, std::size_t Alignment>
26 {
27  new (address()) T();
29 }
30 
31 template <typename T, std::size_t StackSize, std::size_t Alignment>
32 inline StackPtr<T, StackSize, Alignment>::StackPtr(std::nullptr_t) : _storage()
33 {
34 }
35 
36 template <typename T, std::size_t StackSize, std::size_t Alignment>
37 inline StackPtr<T, StackSize, Alignment>::StackPtr(const T& data) : _storage()
38 {
39  reset(data);
40 }
41 
42 template <typename T, std::size_t StackSize, std::size_t Alignment>
43 inline StackPtr<T, StackSize, Alignment>::StackPtr(T&& data) : _storage()
44 {
45  reset(std::move(data));
46 }
47 
48 template <typename T, std::size_t StackSize, std::size_t Alignment>
50 {
51  static_assert(StackSize >= sizeof(T), "Array size must be larger");
52  static_assert(alignof(T) <= Alignment, "Alignment must match alignment requirement of T");
53  reset();
54 }
55 
56 template <typename T, std::size_t StackSize, std::size_t Alignment>
57 inline StackPtr<T, StackSize, Alignment>::StackPtr(const StackPtr& other) : _storage()
58 {
59  if (other.isConstructed()) {
60  reset(*other);
61  }
62 }
63 
64 template <typename T, std::size_t StackSize, std::size_t Alignment>
66  StackPtr other)
67 {
68  other.swap(*this);
69  return *this;
70 }
71 
72 template <typename T, std::size_t StackSize, std::size_t Alignment>
74 {
75  if (other.isConstructed()) {
76  this->reset(std::move(*other));
77  }
78 }
79 
80 template <typename T, std::size_t StackSize, std::size_t Alignment>
82 {
83  return static_cast<T*>(address());
84 }
85 
86 template <typename T, std::size_t StackSize, std::size_t Alignment>
88 {
89  return static_cast<const T*>(address());
90 }
91 
92 template <typename T, std::size_t StackSize, std::size_t Alignment>
94 {
95  return *(operator->());
96 }
97 
98 template <typename T, std::size_t StackSize, std::size_t Alignment>
100 {
101  return *(operator->());
102 }
103 
104 template <typename T, std::size_t StackSize, std::size_t Alignment>
106 {
107  return isConstructed();
108 }
109 
110 template <typename T, std::size_t StackSize, std::size_t Alignment>
112 {
113  if (isConstructed()) {
114  static_cast<T*>(address())->~T();
115  setFlag(InitializeStatus, StackPtrFlags::IsDestroyed);
116  }
117 }
118 
119 template <typename T, std::size_t StackSize, std::size_t Alignment>
120 template <typename... Args>
121 inline void StackPtr<T, StackSize, Alignment>::reset(Args&&... args)
122 {
123  reset();
124  new (address()) T(std::forward<Args>(args)...);
125  setFlag(InitializeStatus, StackPtrFlags::IsConstructed);
126 }
127 
128 template <typename T, std::size_t StackSize, std::size_t Alignment>
130 {
131  using std::swap;
132  StackPtr* reset_after_swap = nullptr;
133  std::size_t remaining_bytes_to_swap = OverheadSize;
134 
135  if (this->isConstructed()) {
136  if (!other.isConstructed()) {
137  other.reset(T());
138  reset_after_swap = this;
139  }
140  swap(*(*this), *other);
141  }
142  else if (other.isConstructed()) {
143  this->reset(T());
144  reset_after_swap = &other;
145  swap(*(*this), *other);
146  }
147  else {
148  remaining_bytes_to_swap = StorageSize;
149  }
150 
151  // either swap overhead or the entire storage
152  while (remaining_bytes_to_swap) {
153  using std::swap;
154  const std::size_t storage_index = StorageSize - remaining_bytes_to_swap--;
155  swap(this->_storage[storage_index], other._storage[storage_index]);
156  }
157 
158  if (reset_after_swap) {
159  reset_after_swap->reset();
160  }
161 }
162 
163 template <typename T, std::size_t StackSize, std::size_t Alignment>
165 {
166  return &_storage;
167 }
168 
169 template <typename T, std::size_t StackSize, std::size_t Alignment>
171 {
172  return &_storage;
173 }
174 
175 template <typename T, std::size_t StackSize, std::size_t Alignment>
178 {
179  _storage[position] = static_cast<typename std::underlying_type<StackPtrFlags>::type>(flag);
180 }
181 
182 template <typename T, std::size_t StackSize, std::size_t Alignment>
184 {
185  return _storage[InitializeStatus] ==
186  static_cast<typename std::underlying_type<StackPtrFlags>::type>(
187  StackPtrFlags::IsConstructed);
188 }
189 
190 template <typename T, std::size_t StackSize, std::size_t Alignment>
192 {
193  lhs.swap(rhs);
194 }
195 
196 template <typename T, std::size_t StackSize, std::size_t Alignment>
197 inline bool operator==(const StackPtr<T, StackSize, Alignment>& lhs,
198  const StackPtr<T, StackSize, Alignment>& rhs)
199 {
200  std::size_t remaining_bytes_to_compare = StackPtr<T, StackSize, Alignment>::OverheadSize;
201  if (!lhs.isConstructed() && !rhs.isConstructed()) {
202  remaining_bytes_to_compare = StackPtr<T, StackSize, Alignment>::StorageSize;
203  }
204  else if (lhs.isConstructed() ^ rhs.isConstructed()) {
205  return false;
206  }
207  else if (!(*lhs == *rhs)) {
208  // fully intended, requires only comparison operator!
209  return false;
210  }
211 
212  // don't use memory::compare to avoid link dependency to memory component
213  bool is_equal = true;
214  while (remaining_bytes_to_compare && is_equal) {
215  const std::size_t storage_index =
216  StackPtr<T, StackSize, Alignment>::StorageSize - remaining_bytes_to_compare--;
217  is_equal = lhs._storage[storage_index] == rhs._storage[storage_index];
218  }
219  return is_equal;
220 }
221 
222 template <typename T, std::size_t StackSize, std::size_t Alignment>
225 {
226  return !(lhs == rhs);
227 }
228 
229 template <typename T, std::size_t StackSize, std::size_t Alignment, typename... Args>
230 constexpr inline auto makeStackPtr(Args&&... args) -> StackPtr<T, StackSize, Alignment>
231 {
232  return StackPtr<T, StackSize, Alignment>(T(std::forward<Args>(args)...));
233 }
234 
235 } // namespace memory
236 } // namespace a_util
237 
238 #endif // A_UTIL_UTIL_MEMORY_DETAIL_STACK_PTR_IMPLL_HEADER_INCLUDED
tBool operator==(const tErrorCode &lhs, const tErrorCode &rhs)
Compare two POD error code types for equality.
A smart pointer allocating its memory only on the stack.
std::array< char, StorageSize > _storage
Aligned storage large enough to contain one object of type T and some overhead for flags.
StackPtr()
Initializes the storage and constructs object ot type T by calling its default ctor.
StackPtrFlags
Flags for StackPtrFlagPositions.
@ IsConstructed
for InitializeStatus --> contained object constructed
void setFlag(StackPtrFlagPositions position, StackPtrFlags flag)
Sets a flag to the appropriate position in the overhead section of the storage.
bool isConstructed() const noexcept
Check whether the object hidden by the storage got constructed.
T & operator*()
Operator overload to use this class like a raw pointer.
T * operator->()
Operator overload to use this class like a raw pointer.
void swap(StackPtr &other)
Swap storage of *this with storage of other stack pointer.
StackPtr & operator=(StackPtr other)
Assignment operator.
@ StorageSize
Entire size of the _storage, including aligned overhead for necessary flags.
@ OverheadSize
Size of the overhead containing the flags (complying to alignment)
void reset()
Unitializes the storage and, if constructed, destructs the storaged object.
StackPtrFlagPositions
Absolute bit positions of the flags inside the overhead area of the storage.
@ InitializeStatus
Flag position for the initialize status.
void * address()
Get pointer to beginning of the storage.
void swap(StackPtr< T, StackSize, Alignment > &lhs, StackPtr< T, StackSize, Alignment > &rhs)
Swap storages of two objects of type StackPtr.
constexpr auto makeStackPtr(Args &&... args) -> StackPtr< T, StackSize, Alignment >
Create a new StackPtr.
bool operator!=(const StackPtr< T, StackSize, Alignment > &lhs, const StackPtr< T, StackSize, Alignment > &rhs)
Compare for inequality.
Serves as the root component, with common functionality documented in core functionality.
Definition: base.h:24
tResult is_equal(const ant::IProperties &oLeftProperties, const ant::IProperties &oRightProperties)
Check if two property sets are equal.
tResult reset(T &oCodec, const A_UTILS_NS::cString &strElementName)
Set the value of the requested element to zero.
Alignment
Alignment defintion.
Public API for StackPtr type and functions.