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