Project
Loading...
Searching...
No Matches
Stack.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11#ifndef O2_HEADERS_STACK_H
12#define O2_HEADERS_STACK_H
13
14#include "Headers/DataHeader.h"
15
16#include <memory_resource>
17
18namespace o2::header
19{
20//__________________________________________________________________________________________________
31// Stack::Stack(const T& header1, const T& header2, ...)
32// - arguments can be headers, or stacks, all will be concatenated in a new Stack
34struct Stack {
35
37
38 private:
39 struct freeobj {
40 freeobj(memory_resource* mr) : resource(mr) {}
41 memory_resource* resource{nullptr};
42 void operator()(std::byte* ptr) { resource->deallocate(ptr, 0, alignof(std::max_align_t)); }
43 };
44
45 public:
47 using value_type = std::byte;
48 using BufferType = std::unique_ptr<value_type[], freeobj>; // this gives us proper default move semantics for free
49
50 Stack() = default;
51 Stack(Stack&&) = default;
52 Stack(Stack&) = delete;
53 Stack& operator=(Stack&) = delete;
54 Stack& operator=(Stack&&) = delete;
55
56 [[nodiscard]] value_type* data() const { return buffer.get(); }
57 [[nodiscard]] size_t size() const { return bufferSize; }
58 allocator_type get_allocator() const { return allocator; }
59 [[nodiscard]] const BaseHeader* first() const { return reinterpret_cast<const BaseHeader*>(this->data()); }
60 static const BaseHeader* firstHeader(std::byte const* buf) { return BaseHeader::get(buf); }
61 static const BaseHeader* lastHeader(std::byte const* buf)
62 {
63 const BaseHeader* last{firstHeader(buf)};
64 while (last && last->flagsNextHeader) {
65 last = last->next();
66 }
67 return last;
68 }
69 static size_t headerStackSize(std::byte const* buf)
70 {
71 size_t result = 0;
72 const BaseHeader* last{firstHeader(buf)};
73 if (last) {
74 while (last->flagsNextHeader) {
75 result += last->size();
76 last = last->next();
77 }
78 result += last->size();
79 }
80 return result;
81 }
82
83 //______________________________________________________________________________________________
89 template <typename FirstArgType, typename... Headers,
90 typename std::enable_if_t<
91 !std::is_convertible<FirstArgType, std::pmr::polymorphic_allocator<std::byte>>::value, int> = 0>
92 Stack(FirstArgType&& firstHeader, Headers&&... headers)
93 : Stack(std::pmr::new_delete_resource(), std::forward<FirstArgType>(firstHeader),
94 std::forward<Headers>(headers)...)
95 {
96 }
97
98 //______________________________________________________________________________________________
99 template <typename... Headers>
100 Stack(const allocator_type allocatorArg, Headers&&... headers)
101 : allocator{allocatorArg},
102 bufferSize{calculateSize(std::forward<Headers>(headers)...)},
103 buffer{static_cast<std::byte*>(allocator.resource()->allocate(bufferSize, alignof(std::max_align_t))), freeobj{allocator.resource()}}
104 {
105 if constexpr (sizeof...(headers) > 1) {
106 injectAll(buffer.get(), std::forward<Headers>(headers)...);
107 } else if (sizeof...(headers) == 1) {
108 injectBool(buffer.get(), std::forward<Headers>(headers)..., false);
109 }
110 }
111
112 //______________________________________________________________________________________________
113 template <typename T, typename... Args>
114 constexpr static size_t calculateSize(T&& h, Args&&... args) noexcept
115 {
116 return calculateSize(std::forward<T>(h)) + calculateSize(std::forward<Args>(args)...);
117 }
118
119 //______________________________________________________________________________________________
120 template <typename T>
121 constexpr static size_t calculateSize(T&& h) noexcept
122 {
123 // if it's a pointer (to a stack) traverse it
124 if constexpr (std::is_convertible_v<T, std::byte*>) {
125 const BaseHeader* next = BaseHeader::get(std::forward<T>(h));
126 if (!next) {
127 return 0;
128 }
129 size_t size = next->size();
130 while ((next = next->next())) {
131 size += next->size();
132 }
133 return size;
134 // otherwise get the size directly
135 } else {
136 return h.size();
137 }
138 }
139
140 // recursion terminator
141 constexpr static size_t calculateSize() { return 0; }
142
143 private:
144 allocator_type allocator{std::pmr::new_delete_resource()};
145 size_t bufferSize{0};
146 BufferType buffer{nullptr, freeobj{allocator.resource()}};
147
148 //______________________________________________________________________________________________
149 template <typename T>
150 static std::byte* injectBool(std::byte* here, T&& h, bool more) noexcept
151 {
152 using headerType = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
153 if (here == nullptr) {
154 return nullptr;
155 }
156 if constexpr (std::is_same_v<headerType, Stack>) {
157 if (h.data() == nullptr) {
158 return here;
159 }
160 std::copy(h.data(), h.data() + h.size(), here);
161 BaseHeader* last = const_cast<BaseHeader*>(lastHeader(here));
162 if (!last) {
163 return here;
164 }
165 last->flagsNextHeader = more;
166 return here + h.size();
167 } else if constexpr (std::is_same_v<BaseHeader, headerType>) {
168 std::copy(h.data(), h.data() + h.size(), here);
169 reinterpret_cast<BaseHeader*>(here)->flagsNextHeader = more;
170 return here + h.size();
171 } else if constexpr (std::is_base_of_v<BaseHeader, headerType>) {
172 ::new (static_cast<void*>(here)) headerType(std::forward<T>(h));
173 reinterpret_cast<BaseHeader*>(here)->flagsNextHeader = more;
174 return here + h.size();
175 } else if constexpr (std::is_same_v<headerType, std::byte*>) {
177 BaseHeader* last{nullptr};
178 while (from) {
179 last = reinterpret_cast<BaseHeader*>(here);
180 std::copy(from->data(), from->data() + from->size(), here);
181 here += from->size();
182 from = from->next();
183 };
184 if (last) {
185 last->flagsNextHeader = more;
186 }
187 return here;
188 } else {
189 static_assert(true, "Stack can only be constructed from other stacks and BaseHeader derived classes");
190 }
191 }
192
193 //______________________________________________________________________________________________
194 template <typename T, typename... Args>
195 static std::byte* injectAll(std::byte* here, T&& h, Args&&... args) noexcept
196 {
197 bool more = hasNonEmptyArg(args...);
198 auto alsohere = injectBool(here, h, more);
199 if constexpr (sizeof...(args) > 1) {
200 return injectAll(alsohere, args...);
201 } else {
202 return injectBool(alsohere, args..., false);
203 }
204 }
205
206 //______________________________________________________________________________________________
207 // helper function to check if there is at least one non-empty header/stack in the argument pack
208 template <typename T, typename... Args>
209 static bool hasNonEmptyArg(const T& h, const Args&... args) noexcept
210 {
211 if (h.size() > 0) {
212 return true;
213 }
214 return hasNonEmptyArg(args...);
215 }
216
217 //______________________________________________________________________________________________
218 template <typename T>
219 static bool hasNonEmptyArg(const T& h) noexcept
220 {
221 if constexpr (std::is_convertible_v<T, std::byte*>) {
222 return get<BaseHeader*>(h);
223 } else {
224 if (h.size() > 0) {
225 return true;
226 }
227 return false;
228 };
229 }
230};
231
232} // namespace o2::header
233
234#endif // HEADERS_STACK_H
TBranch * ptr
Class for time synchronization of RawReader instances.
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint buffer
Definition glcorearb.h:655
GLsizeiptr size
Definition glcorearb.h:659
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
O2 data header classes and API, v0.1.
Definition DetID.h:49
Defining DataPointCompositeObject explicitly as copiable.
the base header struct Every header type must begin (i.e. derive) with this. Don't use this struct di...
Definition DataHeader.h:351
static const BaseHeader * get(const std::byte *b, size_t=0)
access header in buffer
Definition DataHeader.h:405
const BaseHeader * next() const noexcept
get the next header if any (const version)
Definition DataHeader.h:425
constexpr uint32_t size() const noexcept
Definition DataHeader.h:421
a move-only header stack with serialized headers This is the flat buffer where all the headers in a m...
Definition Stack.h:34
size_t size() const
Definition Stack.h:57
Stack & operator=(Stack &&)=delete
std::pmr::polymorphic_allocator< std::byte > allocator_type
Definition Stack.h:46
Stack(FirstArgType &&firstHeader, Headers &&... headers)
Definition Stack.h:92
std::unique_ptr< value_type[], freeobj > BufferType
Definition Stack.h:48
static constexpr size_t calculateSize(T &&h) noexcept
Definition Stack.h:121
static constexpr size_t calculateSize()
Definition Stack.h:141
Stack(Stack &&)=default
allocator_type get_allocator() const
Definition Stack.h:58
const BaseHeader * first() const
Definition Stack.h:59
static const BaseHeader * firstHeader(std::byte const *buf)
Definition Stack.h:60
std::byte value_type
Definition Stack.h:47
static const BaseHeader * lastHeader(std::byte const *buf)
Definition Stack.h:61
value_type * data() const
Definition Stack.h:56
Stack(Stack &)=delete
Stack(const allocator_type allocatorArg, Headers &&... headers)
Definition Stack.h:100
Stack & operator=(Stack &)=delete
static constexpr size_t calculateSize(T &&h, Args &&... args) noexcept
Definition Stack.h:114
static size_t headerStackSize(std::byte const *buf)
Definition Stack.h:69