Skip to content

Commit fb7a17a

Browse files
committed
Modernize o2::header::Stack
- Use concept rather than enable_if, catching cases where a non-BaseHeader is inserted in the Stack. - Cleanup clang-tidy recommendations
1 parent f248969 commit fb7a17a

File tree

1 file changed

+29
-26
lines changed
  • DataFormats/Headers/include/Headers

1 file changed

+29
-26
lines changed

DataFormats/Headers/include/Headers/Stack.h

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,20 @@
1111
#ifndef O2_HEADERS_STACK_H
1212
#define O2_HEADERS_STACK_H
1313

14-
#include "MemoryResources/MemoryResources.h"
15-
#include "Headers/DataHeader.h"
14+
#include "MemoryResources/MemoryResources.h" // IWYU pragma: export
15+
#include "Headers/DataHeader.h" // IWYU pragma: export
16+
#include <type_traits>
17+
18+
template <typename T>
19+
concept PolymorphicAllocatorLike = requires(T& t) {
20+
{ t.allocate(0) };
21+
{ t.deallocate(nullptr, 0) };
22+
};
1623

17-
namespace o2
18-
{
24+
template <typename T>
25+
concept DataHeaderLike = std::is_convertible_v<T, o2::header::BaseHeader>;
1926

20-
namespace header
27+
namespace o2::header
2128
{
2229
//__________________________________________________________________________________________________
2330
/// @struct Stack
@@ -47,18 +54,18 @@ struct Stack {
4754
public:
4855
using allocator_type = boost::container::pmr::polymorphic_allocator<std::byte>;
4956
using value_type = std::byte;
50-
using BufferType = std::unique_ptr<value_type[], freeobj>; //this gives us proper default move semantics for free
57+
using BufferType = std::unique_ptr<value_type[], freeobj>; // this gives us proper default move semantics for free
5158

5259
Stack() = default;
5360
Stack(Stack&&) = default;
5461
Stack(Stack&) = delete;
5562
Stack& operator=(Stack&) = delete;
5663
Stack& operator=(Stack&&) = default;
5764

58-
value_type* data() const { return buffer.get(); }
59-
size_t size() const { return bufferSize; }
60-
allocator_type get_allocator() const { return allocator; }
61-
const BaseHeader* first() const { return reinterpret_cast<const BaseHeader*>(this->data()); }
65+
[[nodiscard]] value_type* data() const { return buffer.get(); }
66+
[[nodiscard]] size_t size() const { return bufferSize; }
67+
[[nodiscard]] allocator_type get_allocator() const { return allocator; }
68+
[[nodiscard]] const BaseHeader* first() const { return reinterpret_cast<const BaseHeader*>(this->data()); }
6269
static const BaseHeader* firstHeader(std::byte const* buf) { return BaseHeader::get(buf); }
6370
static const BaseHeader* lastHeader(std::byte const* buf)
6471
{
@@ -88,18 +95,15 @@ struct Stack {
8895
/// allocation is done using new_delete_resource.
8996
/// In the final stack the first header must be DataHeader.
9097
/// all headers must derive from BaseHeader, in addition also other stacks can be passed to ctor.
91-
template <typename FirstArgType, typename... Headers,
92-
typename std::enable_if_t<
93-
!std::is_convertible<FirstArgType, boost::container::pmr::polymorphic_allocator<std::byte>>::value, int> = 0>
94-
Stack(FirstArgType&& firstHeader, Headers&&... headers)
95-
: Stack(boost::container::pmr::new_delete_resource(), std::forward<FirstArgType>(firstHeader),
96-
std::forward<Headers>(headers)...)
98+
template <DataHeaderLike... Headers>
99+
Stack(Headers&&... headers)
100+
: Stack(boost::container::pmr::new_delete_resource(), std::forward<Headers>(headers)...)
97101
{
98102
}
99103

100104
//______________________________________________________________________________________________
101-
template <typename... Headers>
102-
Stack(const allocator_type allocatorArg, Headers&&... headers)
105+
template <PolymorphicAllocatorLike Allocator, DataHeaderLike... Headers>
106+
Stack(Allocator allocatorArg, Headers&&... headers)
103107
: allocator{allocatorArg},
104108
bufferSize{calculateSize(std::forward<Headers>(headers)...)},
105109
buffer{static_cast<std::byte*>(allocator.resource()->allocate(bufferSize, alignof(std::max_align_t))), freeobj{allocator.resource()}}
@@ -122,9 +126,9 @@ struct Stack {
122126
template <typename T>
123127
constexpr static size_t calculateSize(T&& h) noexcept
124128
{
125-
//if it's a pointer (to a stack) traverse it
129+
// if it's a pointer (to a stack) traverse it
126130
if constexpr (std::is_convertible_v<T, std::byte*>) {
127-
const BaseHeader* next = BaseHeader::get(std::forward<T>(h));
131+
const o2::header::BaseHeader* next = o2::header::BaseHeader::get(std::forward<T>(h));
128132
if (!next) {
129133
return 0;
130134
}
@@ -133,13 +137,13 @@ struct Stack {
133137
size += next->size();
134138
}
135139
return size;
136-
//otherwise get the size directly
140+
// otherwise get the size directly
137141
} else {
138142
return h.size();
139143
}
140144
}
141145

142-
//recursion terminator
146+
// recursion terminator
143147
constexpr static size_t calculateSize() { return 0; }
144148

145149
private:
@@ -160,13 +164,13 @@ struct Stack {
160164
return here;
161165
}
162166
std::copy(h.data(), h.data() + h.size(), here);
163-
BaseHeader* last = const_cast<BaseHeader*>(lastHeader(here));
167+
auto* last = const_cast<BaseHeader*>(lastHeader(here));
164168
if (!last) {
165169
return here;
166170
}
167171
last->flagsNextHeader = more;
168172
return here + h.size();
169-
} else if constexpr (std::is_same_v<BaseHeader, headerType>) {
173+
} else if constexpr (std::is_same_v<o2::header::BaseHeader, headerType>) {
170174
std::copy(h.data(), h.data() + h.size(), here);
171175
reinterpret_cast<BaseHeader*>(here)->flagsNextHeader = more;
172176
return here + h.size();
@@ -231,7 +235,6 @@ struct Stack {
231235
}
232236
};
233237

234-
} // namespace header
235-
} // namespace o2
238+
} // namespace o2::header
236239

237240
#endif // HEADERS_STACK_H

0 commit comments

Comments
 (0)