DUNE-DAQ
DUNE Trigger and Data Acquisition software
Toggle main menu visibility
Loading...
Searching...
No Matches
dunedaq
sourcecode
datahandlinglibs
include
datahandlinglibs
models
IterableQueueModel.hpp
Go to the documentation of this file.
1
17
18
// @author Bo Hu (bhu@fb.com)
19
// @author Jordan DeLong (delong.j@fb.com)
20
21
// Modification by Roland Sipos and Florian Till Groetschla
22
// for DUNE-DAQ software framework
23
24
#ifndef DATAHANDLINGLIBS_INCLUDE_DATAHANDLINGLIBS_MODELS_ITERABLEQUEUEMODEL_HPP_
25
#define DATAHANDLINGLIBS_INCLUDE_DATAHANDLINGLIBS_MODELS_ITERABLEQUEUEMODEL_HPP_
26
27
#include "
datahandlinglibs/DataHandlingIssues.hpp
"
28
#include "
datahandlinglibs/concepts/LatencyBufferConcept.hpp
"
29
30
#include "
datahandlinglibs/opmon/datahandling_info.pb.h
"
31
32
#include "
logging/Logging.hpp
"
33
34
#include <folly/lang/Align.h>
35
36
#include <atomic>
37
#include <cassert>
38
#include <cstddef>
39
#include <cstdlib>
40
#include <cxxabi.h>
41
#include <iomanip>
42
#include <iostream>
43
#include <limits>
44
#include <memory>
45
#include <mutex>
46
#include <new>
47
#include <stdexcept>
48
#include <thread>
49
#include <type_traits>
50
#include <utility>
51
52
#include <xmmintrin.h>
53
54
#ifdef WITH_LIBNUMA_SUPPORT
55
#include <numa.h>
56
#endif
57
58
namespace
dunedaq
{
59
namespace
datahandlinglibs
{
60
70
template
<
class
T>
71
struct
IterableQueueModel
:
public
LatencyBufferConcept
<T>
72
{
73
typedef
T
value_type
;
74
75
static
constexpr
bool
expects_order
=
true
;
76
77
IterableQueueModel
(
const
IterableQueueModel
&) =
delete
;
78
IterableQueueModel
&
operator=
(
const
IterableQueueModel
&) =
delete
;
79
80
// Default constructor
81
IterableQueueModel
()
82
:
LatencyBufferConcept
<T>()
83
,
numa_aware_
(false)
84
,
numa_node_
(0)
85
,
intrinsic_allocator_
(false)
86
,
alignment_size_
(0)
87
,
invalid_configuration_requested_
(false)
88
,
prefill_ready_
(false)
89
,
prefill_done_
(false)
90
,
size_
(2)
91
,
records_
(static_cast<T*>(
std
::malloc(sizeof(T) * 2)))
92
,
readIndex_
(0)
93
,
writeIndex_
(0)
94
{}
95
96
// Constructor with alignment strategies
97
IterableQueueModel
(std::size_t
size
,
// size must be >= 2
98
bool
numa_aware =
false
,
99
uint8_t numa_node = 0,
// NOLINT (build/unsigned)
100
bool
intrinsic_allocator =
false
,
101
std::size_t alignment_size = 0)
102
:
LatencyBufferConcept
<T>()
// NOLINT(build/unsigned)
103
,
numa_aware_
(numa_aware)
104
,
numa_node_
(numa_node)
105
,
intrinsic_allocator_
(intrinsic_allocator)
106
,
alignment_size_
(alignment_size)
107
,
invalid_configuration_requested_
(false)
108
,
prefill_ready_
(false)
109
,
prefill_done_
(false)
110
,
size_
(
size
)
111
,
readIndex_
(0)
112
,
writeIndex_
(0)
113
{
114
assert(
size
>= 2);
115
allocate_memory
(
size
, numa_aware, numa_node, intrinsic_allocator, alignment_size);
116
117
if
(!
records_
) {
118
throw
std::bad_alloc();
119
}
120
#if 0
121
ptrlogger
= std::thread([&](){
122
while
(
true
) {
123
auto
const
currentRead =
readIndex_
.load(std::memory_order_relaxed);
124
auto
const
currentWrite =
writeIndex_
.load(std::memory_order_relaxed);
125
TLOG
() <<
"BEG:"
<< std::hex << &
records_
[0] <<
" END:"
<< &
records_
[
size
] << std::dec
126
<<
" R:"
<< currentRead <<
" - W:"
<< currentWrite
127
<<
" OFLOW:"
<<
overflow_ctr
;
128
std::this_thread::sleep_for(std::chrono::milliseconds(100));
129
}
130
});
131
#endif
132
}
133
134
// Destructor
135
~IterableQueueModel
() {
free_memory
(); }
136
137
// Free allocated memory that is different for alignment strategies and allocation policies
138
void
free_memory
();
139
140
// Allocate memory based on different alignment strategies and allocation policies
141
void
allocate_memory
(std::size_t
size
,
142
bool
numa_aware
/*= false*/
,
143
uint8_t numa_node = 0,
// NOLINT (build/unsigned)
144
bool
intrinsic_allocator =
false
,
145
std::size_t alignment_size = 0);
146
147
void
allocate_memory
(std::size_t
size
)
override
{
allocate_memory
(
size
,
false
); }
148
149
// Task that fills up the LB.
150
void
prefill_task
();
151
152
// Issue fre-fill task
153
void
force_pagefault
();
154
155
// Write element into the queue
156
bool
write
(T&& record)
override
;
157
158
// Read element from a queue (move or copy the value at the front of the queue to given variable)
159
bool
read
(T& record)
override
;
160
161
// Pop element on front of queue
162
void
popFront
();
163
164
// Pop number of elements (X) from the front of the queue
165
void
pop
(std::size_t x);
166
167
// Returns true if the queue is empty
168
bool
isEmpty
()
const
;
169
170
// Returns true if write index reached read index
171
bool
isFull
()
const
;
172
173
// Returns a good-enough guess on current occupancy:
174
// * If called by consumer, then true size may be more (because producer may
175
// be adding items concurrently).
176
// * If called by producer, then true size may be less (because consumer may
177
// be removing items concurrently).
178
// * It is undefined to call this from any other thread.
179
std::size_t
occupancy
()
const override
;
180
181
// The size of the underlying buffer, not the amount of usable slots
182
std::size_t
size
()
const
{
return
size_
; }
183
184
// Maximum number of items in the queue.
185
std::size_t
capacity
()
const
{
return
size_
- 1; }
186
187
// Gives a pointer to the current read index
188
const
T*
front
()
override
;
189
190
// Gives a pointer to the last written element
191
const
T*
back
()
override
;
192
193
// Gives a pointer to the first available slot of the queue
194
T*
start_of_buffer
() {
return
&
records_
[0]; }
195
196
// Gives a pointer to the last available slot of the queue
197
T*
end_of_buffer
() {
return
&
records_
[
size_
]; }
198
199
// Configures the model
200
void
conf
(
const
appmodel::LatencyBuffer
* cfg)
override
;
201
202
// Unconfigures the model
203
void
scrap
(
const
appfwk::DAQModule::CommandData_t&
/*cfg*/
)
override
;
204
205
// Flushes the elements from the queue
206
void
flush
()
override
{
pop
(
occupancy
()); }
207
208
// Returns the current memory alignment size
209
std::size_t
get_alignment_size
() {
return
alignment_size_
; }
210
211
// Iterator for elements in the queue
212
struct
Iterator
213
{
214
using
iterator_category
= std::forward_iterator_tag;
215
using
difference_type
= std::ptrdiff_t;
216
using
value_type
= T;
217
using
pointer
= T*;
218
using
reference
= T&;
219
220
Iterator
(
IterableQueueModel<T>
& queue, uint32_t index)
// NOLINT(build/unsigned)
221
:
m_queue
(queue)
222
,
m_index
(index)
223
{}
224
225
reference
operator*
()
const
{
return
m_queue
.records_[
m_index
]; }
226
pointer
operator->
() {
return
&
m_queue
.records_[
m_index
]; }
227
Iterator
&
operator++
()
// NOLINT(runtime/increment_decrement) :)
228
{
229
if
(
good
()) {
230
m_index
++;
231
if
(
m_index
==
m_queue
.size_) {
232
m_index
= 0;
233
}
234
}
235
if
(!
good
()) {
236
m_index
= std::numeric_limits<uint32_t>::max();
// NOLINT(build/unsigned)
237
}
238
return
*
this
;
239
}
240
Iterator
operator++
(
int
amount)
// NOLINT(runtime/increment_decrement) :)
241
{
242
Iterator
tmp = *
this
;
243
for
(
int
i = 0; i < amount; ++i) {
244
++(*this);
245
}
246
return
tmp;
247
}
248
friend
bool
operator==
(
const
Iterator
& a,
const
Iterator
& b) {
return
a.
m_index
== b.
m_index
; }
249
friend
bool
operator!=
(
const
Iterator
& a,
const
Iterator
& b) {
return
a.
m_index
!= b.
m_index
; }
250
251
bool
good
()
252
{
253
auto
const
currentRead =
m_queue
.readIndex_.load(std::memory_order_relaxed);
254
auto
const
currentWrite =
m_queue
.writeIndex_.load(std::memory_order_relaxed);
255
return
(*
this
!=
m_queue
.end()) &&
256
((
m_index
>= currentRead &&
m_index
< currentWrite) ||
257
(
m_index
>= currentRead && currentWrite < currentRead) ||
258
(currentWrite < currentRead &&
m_index
< currentRead &&
m_index
< currentWrite));
259
}
260
261
uint32_t
get_index
() {
return
m_index
; }
// NOLINT(build/unsigned)
262
263
private
:
264
IterableQueueModel<T>
&
m_queue
;
265
uint32_t
m_index
;
// NOLINT(build/unsigned)
266
};
267
268
Iterator
begin
()
269
{
270
auto
const
currentRead =
readIndex_
.load(std::memory_order_relaxed);
271
if
(currentRead ==
writeIndex_
.load(std::memory_order_acquire)) {
272
// queue is empty
273
return
end
();
274
}
275
return
Iterator
(*
this
, currentRead);
276
}
277
278
Iterator
end
()
279
{
280
return
Iterator
(*
this
, std::numeric_limits<uint32_t>::max());
// NOLINT(build/unsigned)
281
}
282
283
protected
:
284
virtual
void
generate_opmon_data
()
override
;
285
286
// Hidden original write implementation with signature difference. Only used for pre-allocation
287
template
<
class
... Args>
288
bool
write_
(Args&&... recordArgs);
289
290
// Counter for failed writes, due to the fact the queue is full
291
std::atomic<int>
overflow_ctr
{ 0 };
292
293
// NUMA awareness and aligned allocator usage configuration
294
bool
numa_aware_
;
295
uint8_t
numa_node_
;
// NOLINT (build/unsigned)
296
bool
intrinsic_allocator_
;
297
std::size_t
alignment_size_
;
298
bool
invalid_configuration_requested_
;
299
300
// Pre-fill and page-fault internal thread control
301
std::string
prefiller_name_
{
"lbpfn"
};
302
std::mutex
prefill_mutex_
;
303
std::condition_variable
prefill_cv_
;
304
bool
prefill_ready_
;
305
bool
prefill_done_
;
306
307
// Ptr logger for debugging
308
std::thread
ptrlogger
;
309
310
// Underlying buffer with padding:
311
// * hardware_destructive_interference_size is set to 128.
312
// * (Assuming cache line size of 64, so we use a cache line pair size of 128)
313
char
pad0_
[folly::hardware_destructive_interference_size];
// NOLINT(runtime/arrays)
314
uint32_t
size_
;
// NOLINT(build/unsigned)
315
T*
records_
;
316
alignas
(
317
folly::hardware_destructive_interference_size) std::atomic<unsigned int>
readIndex_
;
// NOLINT(build/unsigned)
318
alignas
(
319
folly::hardware_destructive_interference_size) std::atomic<unsigned int>
writeIndex_
;
// NOLINT(build/unsigned)
320
char
pad1_
[folly::hardware_destructive_interference_size -
sizeof
(
writeIndex_
)];
// NOLINT(runtime/arrays)
321
};
322
323
}
// namespace datahandlinglibs
324
}
// namespace dunedaq
325
326
// Declarations
327
#include "
detail/IterableQueueModel.hxx
"
328
329
#endif
// DATAHANDLINGLIBS_INCLUDE_DATAHANDLINGLIBS_MODELS_ITERABLEQUEUEMODEL_HPP_
DataHandlingIssues.hpp
IterableQueueModel.hxx
LatencyBufferConcept.hpp
dunedaq::appmodel::LatencyBuffer
Definition
LatencyBuffer.hpp:20
dunedaq::datahandlinglibs::LatencyBufferConcept::LatencyBufferConcept
LatencyBufferConcept()
Definition
LatencyBufferConcept.hpp:34
datahandling_info.pb.h
Logging.hpp
TLOG
#define TLOG(...)
Definition
macro.hpp:22
dunedaq::datahandlinglibs
Definition
DataHandlingConcept.hpp:16
dunedaq
Including Qt Headers.
Definition
module.cpp:16
dunedaq::size
FELIX Initialization std::string initerror FELIX queue timed std::string queuename Unexpected chunk size
Definition
FelixIssues.hpp:28
std
Definition
SchemaUtils.hpp:118
dunedaq::datahandlinglibs::IterableQueueModel::Iterator
Definition
IterableQueueModel.hpp:213
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::reference
T & reference
Definition
IterableQueueModel.hpp:218
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::iterator_category
std::forward_iterator_tag iterator_category
Definition
IterableQueueModel.hpp:214
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::operator!=
friend bool operator!=(const Iterator &a, const Iterator &b)
Definition
IterableQueueModel.hpp:249
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::good
bool good()
Definition
IterableQueueModel.hpp:251
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::get_index
uint32_t get_index()
Definition
IterableQueueModel.hpp:261
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::operator*
reference operator*() const
Definition
IterableQueueModel.hpp:225
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::operator++
Iterator operator++(int amount)
Definition
IterableQueueModel.hpp:240
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::m_queue
IterableQueueModel< T > & m_queue
Definition
IterableQueueModel.hpp:264
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::operator++
Iterator & operator++()
Definition
IterableQueueModel.hpp:227
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::value_type
T value_type
Definition
IterableQueueModel.hpp:216
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::pointer
T * pointer
Definition
IterableQueueModel.hpp:217
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::operator->
pointer operator->()
Definition
IterableQueueModel.hpp:226
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::difference_type
std::ptrdiff_t difference_type
Definition
IterableQueueModel.hpp:215
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::m_index
uint32_t m_index
Definition
IterableQueueModel.hpp:265
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::operator==
friend bool operator==(const Iterator &a, const Iterator &b)
Definition
IterableQueueModel.hpp:248
dunedaq::datahandlinglibs::IterableQueueModel::Iterator::Iterator
Iterator(IterableQueueModel< T > &queue, uint32_t index)
Definition
IterableQueueModel.hpp:220
dunedaq::datahandlinglibs::IterableQueueModel::pad0_
char pad0_[folly::hardware_destructive_interference_size]
Definition
IterableQueueModel.hpp:313
dunedaq::datahandlinglibs::IterableQueueModel::capacity
std::size_t capacity() const
Definition
IterableQueueModel.hpp:185
dunedaq::datahandlinglibs::IterableQueueModel::prefill_ready_
bool prefill_ready_
Definition
IterableQueueModel.hpp:304
dunedaq::datahandlinglibs::IterableQueueModel::get_alignment_size
std::size_t get_alignment_size()
Definition
IterableQueueModel.hpp:209
dunedaq::datahandlinglibs::IterableQueueModel::isFull
bool isFull() const
Definition
IterableQueueModel.hxx:233
dunedaq::datahandlinglibs::IterableQueueModel::size_
uint32_t size_
Definition
IterableQueueModel.hpp:314
dunedaq::datahandlinglibs::IterableQueueModel::IterableQueueModel
IterableQueueModel()
Definition
IterableQueueModel.hpp:81
dunedaq::datahandlinglibs::IterableQueueModel::flush
void flush() override
Flush all elements from the latency buffer.
Definition
IterableQueueModel.hpp:206
dunedaq::datahandlinglibs::IterableQueueModel::overflow_ctr
std::atomic< int > overflow_ctr
Definition
IterableQueueModel.hpp:291
dunedaq::datahandlinglibs::IterableQueueModel::value_type
T value_type
Definition
IterableQueueModel.hpp:73
dunedaq::datahandlinglibs::IterableQueueModel::end
Iterator end()
Definition
IterableQueueModel.hpp:278
dunedaq::datahandlinglibs::IterableQueueModel::occupancy
std::size_t occupancy() const override
Occupancy of LB.
Definition
IterableQueueModel.hxx:254
dunedaq::datahandlinglibs::IterableQueueModel::numa_node_
uint8_t numa_node_
Definition
IterableQueueModel.hpp:295
dunedaq::datahandlinglibs::IterableQueueModel::generate_opmon_data
virtual void generate_opmon_data() override
Definition
IterableQueueModel.hxx:372
dunedaq::datahandlinglibs::IterableQueueModel::expects_order
static constexpr bool expects_order
Definition
IterableQueueModel.hpp:75
dunedaq::datahandlinglibs::IterableQueueModel::prefill_mutex_
std::mutex prefill_mutex_
Definition
IterableQueueModel.hpp:302
dunedaq::datahandlinglibs::IterableQueueModel::isEmpty
bool isEmpty() const
Definition
IterableQueueModel.hxx:225
dunedaq::datahandlinglibs::IterableQueueModel::readIndex_
std::atomic< unsigned int > readIndex_
Definition
IterableQueueModel.hpp:317
dunedaq::datahandlinglibs::IterableQueueModel::allocate_memory
void allocate_memory(std::size_t size, bool numa_aware, uint8_t numa_node=0, bool intrinsic_allocator=false, std::size_t alignment_size=0)
Definition
IterableQueueModel.hxx:39
dunedaq::datahandlinglibs::IterableQueueModel::end_of_buffer
T * end_of_buffer()
Definition
IterableQueueModel.hpp:197
dunedaq::datahandlinglibs::IterableQueueModel::prefill_done_
bool prefill_done_
Definition
IterableQueueModel.hpp:305
dunedaq::datahandlinglibs::IterableQueueModel::prefill_cv_
std::condition_variable prefill_cv_
Definition
IterableQueueModel.hpp:303
dunedaq::datahandlinglibs::IterableQueueModel::write_
bool write_(Args &&... recordArgs)
Definition
IterableQueueModel.hxx:342
dunedaq::datahandlinglibs::IterableQueueModel::back
const T * back() override
Get pointer to the back of the LB.
Definition
IterableQueueModel.hxx:279
dunedaq::datahandlinglibs::IterableQueueModel::~IterableQueueModel
~IterableQueueModel()
Definition
IterableQueueModel.hpp:135
dunedaq::datahandlinglibs::IterableQueueModel::popFront
void popFront()
Definition
IterableQueueModel.hxx:198
dunedaq::datahandlinglibs::IterableQueueModel::begin
Iterator begin()
Definition
IterableQueueModel.hpp:268
dunedaq::datahandlinglibs::IterableQueueModel::front
const T * front() override
Get pointer to the front of the LB.
Definition
IterableQueueModel.hxx:267
dunedaq::datahandlinglibs::IterableQueueModel::pad1_
char pad1_[folly::hardware_destructive_interference_size - sizeof(writeIndex_)]
Definition
IterableQueueModel.hpp:320
dunedaq::datahandlinglibs::IterableQueueModel::alignment_size_
std::size_t alignment_size_
Definition
IterableQueueModel.hpp:297
dunedaq::datahandlinglibs::IterableQueueModel::invalid_configuration_requested_
bool invalid_configuration_requested_
Definition
IterableQueueModel.hpp:298
dunedaq::datahandlinglibs::IterableQueueModel::IterableQueueModel
IterableQueueModel(std::size_t size, bool numa_aware=false, uint8_t numa_node=0, bool intrinsic_allocator=false, std::size_t alignment_size=0)
Definition
IterableQueueModel.hpp:97
dunedaq::datahandlinglibs::IterableQueueModel::prefiller_name_
std::string prefiller_name_
Definition
IterableQueueModel.hpp:301
dunedaq::datahandlinglibs::IterableQueueModel::start_of_buffer
T * start_of_buffer()
Definition
IterableQueueModel.hpp:194
dunedaq::datahandlinglibs::IterableQueueModel::records_
T * records_
Definition
IterableQueueModel.hpp:315
dunedaq::datahandlinglibs::IterableQueueModel::write
bool write(T &&record) override
Move referenced object into LB.
Definition
IterableQueueModel.hxx:155
dunedaq::datahandlinglibs::IterableQueueModel::prefill_task
void prefill_task()
Definition
IterableQueueModel.hxx:84
dunedaq::datahandlinglibs::IterableQueueModel::conf
void conf(const appmodel::LatencyBuffer *cfg) override
Configure the LB.
Definition
IterableQueueModel.hxx:297
dunedaq::datahandlinglibs::IterableQueueModel::IterableQueueModel
IterableQueueModel(const IterableQueueModel &)=delete
dunedaq::datahandlinglibs::IterableQueueModel::operator=
IterableQueueModel & operator=(const IterableQueueModel &)=delete
dunedaq::datahandlinglibs::IterableQueueModel::intrinsic_allocator_
bool intrinsic_allocator_
Definition
IterableQueueModel.hpp:296
dunedaq::datahandlinglibs::IterableQueueModel::size
std::size_t size() const
Definition
IterableQueueModel.hpp:182
dunedaq::datahandlinglibs::IterableQueueModel::pop
void pop(std::size_t x)
Pop specified amount of elements from LB.
Definition
IterableQueueModel.hxx:215
dunedaq::datahandlinglibs::IterableQueueModel::writeIndex_
std::atomic< unsigned int > writeIndex_
Definition
IterableQueueModel.hpp:319
dunedaq::datahandlinglibs::IterableQueueModel::scrap
void scrap(const appfwk::DAQModule::CommandData_t &) override
Unconfigure the LB.
Definition
IterableQueueModel.hxx:322
dunedaq::datahandlinglibs::IterableQueueModel::read
bool read(T &record) override
Move object from LB to referenced.
Definition
IterableQueueModel.hxx:177
dunedaq::datahandlinglibs::IterableQueueModel::allocate_memory
void allocate_memory(std::size_t size) override
Definition
IterableQueueModel.hpp:147
dunedaq::datahandlinglibs::IterableQueueModel::free_memory
void free_memory()
Definition
IterableQueueModel.hxx:9
dunedaq::datahandlinglibs::IterableQueueModel::numa_aware_
bool numa_aware_
Definition
IterableQueueModel.hpp:294
dunedaq::datahandlinglibs::IterableQueueModel::force_pagefault
void force_pagefault()
Definition
IterableQueueModel.hxx:107
dunedaq::datahandlinglibs::IterableQueueModel::ptrlogger
std::thread ptrlogger
Definition
IterableQueueModel.hpp:308
Generated on
for DUNE-DAQ by
1.17.0