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
15#include "Headers/DataHeader.h"
16
17namespace o2
18{
19
20namespace header
21{
22//__________________________________________________________________________________________________
33// Stack::Stack(const T& header1, const T& header2, ...)
34// - arguments can be headers, or stacks, all will be concatenated in a new Stack
36struct Stack {
37
38 using memory_resource = o2::pmr::memory_resource;
39
40 private:
41 struct freeobj {
42 freeobj(memory_resource* mr) : resource(mr) {}
43 memory_resource* resource{nullptr};
44 void operator()(std::byte* ptr) { resource->deallocate(ptr, 0, 0); }
45 };
46
47 public:
48 using allocator_type = boost::container::pmr::polymorphic_allocator<std::byte>;
49 using value_type = std::byte;
50 using BufferType = std::unique_ptr<value_type[], freeobj>; //this gives us proper default move semantics for free
51
52 Stack() = default;
53 Stack(Stack&&) = default;
54 Stack(Stack&) = delete;
55 Stack& operator=(Stack&) = delete;
56 Stack& operator=(Stack&&) = default;
57
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()); }
62 static const BaseHeader* firstHeader(std::byte const* buf) { return BaseHeader::get(buf); }
63 static const BaseHeader* lastHeader(std::byte const* buf)
64 {
65 const BaseHeader* last{firstHeader(buf)};
66 while (last && last->flagsNextHeader) {
67 last = last->next();
68 }
69 return last;
70 }
71 static size_t headerStackSize(std::byte const* buf)
72 {
73 size_t result = 0;
74 const BaseHeader* last{firstHeader(buf)};
75 if (last) {
76 while (last->flagsNextHeader) {
77 result += last->size();
78 last = last->next();
79 }
80 result += last->size();
81 }
82 return result;
83 }
84
85 //______________________________________________________________________________________________
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)...)
97 {
98 }
99
100 //______________________________________________________________________________________________
101 template <typename... Headers>
102 Stack(const allocator_type allocatorArg, Headers&&... headers)
103 : allocator{allocatorArg},
104 bufferSize{calculateSize(std::forward<Headers>(headers)...)},
105 buffer{static_cast<std::byte*>(allocator.resource()->allocate(bufferSize, alignof(std::max_align_t))), freeobj{allocator.resource()}}
106 {
107 if constexpr (sizeof...(headers) > 1) {
108 injectAll(buffer.get(), std::forward<Headers>(headers)...);
109 } else if (sizeof...(headers) == 1) {
110 injectBool(buffer.get(), std::forward<Headers>(headers)..., false);
111 }
112 }
113
114 //______________________________________________________________________________________________
115 template <typename T, typename... Args>
116 constexpr static size_t calculateSize(T&& h, Args&&... args) noexcept
117 {
118 return calculateSize(std::forward<T>(h)) + calculateSize(std::forward<Args>(args)...);
119 }
120
121 //______________________________________________________________________________________________
122 template <typename T>
123 constexpr static size_t calculateSize(T&& h) noexcept
124 {
125 //if it's a pointer (to a stack) traverse it
126 if constexpr (std::is_convertible_v<T, std::byte*>) {
127 const BaseHeader* next = BaseHeader::get(std::forward<T>(h));
128 if (!next) {
129 return 0;
130 }
131 size_t size = next->size();
132 while ((next = next->next())) {
133 size += next->size();
134 }
135 return size;
136 //otherwise get the size directly
137 } else {
138 return h.size();
139 }
140 }
141
142 //recursion terminator
143 constexpr static size_t calculateSize() { return 0; }
144
145 private:
146 allocator_type allocator{boost::container::pmr::new_delete_resource()};
147 size_t bufferSize{0};
148 BufferType buffer{nullptr, freeobj{allocator.resource()}};
149
150 //______________________________________________________________________________________________
151 template <typename T>
152 static std::byte* injectBool(std::byte* here, T&& h, bool more) noexcept
153 {
154 using headerType = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
155 if (here == nullptr) {
156 return nullptr;
157 }
158 if constexpr (std::is_same_v<headerType, Stack>) {
159 if (h.data() == nullptr) {
160 return here;
161 }
162 std::copy(h.data(), h.data() + h.size(), here);
163 BaseHeader* last = const_cast<BaseHeader*>(lastHeader(here));
164 if (!last) {
165 return here;
166 }
167 last->flagsNextHeader = more;
168 return here + h.size();
169 } else if constexpr (std::is_same_v<BaseHeader, headerType>) {
170 std::copy(h.data(), h.data() + h.size(), here);
171 reinterpret_cast<BaseHeader*>(here)->flagsNextHeader = more;
172 return here + h.size();
173 } else if constexpr (std::is_base_of_v<BaseHeader, headerType>) {
174 ::new (static_cast<void*>(here)) headerType(std::forward<T>(h));
175 reinterpret_cast<BaseHeader*>(here)->flagsNextHeader = more;
176 return here + h.size();
177 } else if constexpr (std::is_same_v<headerType, std::byte*>) {
179 BaseHeader* last{nullptr};
180 while (from) {
181 last = reinterpret_cast<BaseHeader*>(here);
182 std::copy(from->data(), from->data() + from->size(), here);
183 here += from->size();
184 from = from->next();
185 };
186 if (last) {
187 last->flagsNextHeader = more;
188 }
189 return here;
190 } else {
191 static_assert(true, "Stack can only be constructed from other stacks and BaseHeader derived classes");
192 }
193 }
194
195 //______________________________________________________________________________________________
196 template <typename T, typename... Args>
197 static std::byte* injectAll(std::byte* here, T&& h, Args&&... args) noexcept
198 {
199 bool more = hasNonEmptyArg(args...);
200 auto alsohere = injectBool(here, h, more);
201 if constexpr (sizeof...(args) > 1) {
202 return injectAll(alsohere, args...);
203 } else {
204 return injectBool(alsohere, args..., false);
205 }
206 }
207
208 //______________________________________________________________________________________________
209 // helper function to check if there is at least one non-empty header/stack in the argument pack
210 template <typename T, typename... Args>
211 static bool hasNonEmptyArg(const T& h, const Args&... args) noexcept
212 {
213 if (h.size() > 0) {
214 return true;
215 }
216 return hasNonEmptyArg(args...);
217 }
218
219 //______________________________________________________________________________________________
220 template <typename T>
221 static bool hasNonEmptyArg(const T& h) noexcept
222 {
223 if constexpr (std::is_convertible_v<T, std::byte*>) {
224 return get<BaseHeader*>(h);
225 } else {
226 if (h.size() > 0) {
227 return true;
228 }
229 return false;
230 };
231 }
232};
233
234} // namespace header
235} // namespace o2
236
237#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
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
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:36
size_t size() const
Definition Stack.h:59
Stack(FirstArgType &&firstHeader, Headers &&... headers)
Definition Stack.h:94
std::unique_ptr< value_type[], freeobj > BufferType
Definition Stack.h:50
static constexpr size_t calculateSize(T &&h) noexcept
Definition Stack.h:123
static constexpr size_t calculateSize()
Definition Stack.h:143
Stack(Stack &&)=default
allocator_type get_allocator() const
Definition Stack.h:60
const BaseHeader * first() const
Definition Stack.h:61
boost::container::pmr::polymorphic_allocator< std::byte > allocator_type
Definition Stack.h:48
static const BaseHeader * firstHeader(std::byte const *buf)
Definition Stack.h:62
std::byte value_type
Definition Stack.h:49
static const BaseHeader * lastHeader(std::byte const *buf)
Definition Stack.h:63
value_type * data() const
Definition Stack.h:58
Stack(Stack &)=delete
o2::pmr::memory_resource memory_resource
Definition Stack.h:38
Stack(const allocator_type allocatorArg, Headers &&... headers)
Definition Stack.h:102
Stack & operator=(Stack &)=delete
static constexpr size_t calculateSize(T &&h, Args &&... args) noexcept
Definition Stack.h:116
Stack & operator=(Stack &&)=default
static size_t headerStackSize(std::byte const *buf)
Definition Stack.h:71