1+ #pragma once
2+
3+ #include " backoffScheme.hpp"
4+ #include " doubleBufferedValue.hpp"
5+ #include " mqOutputStorage.hpp"
6+ #include " outputStorage.hpp"
7+ #include " rwSpinlock.hpp"
8+ #include " threadUtils.hpp"
9+
10+ #include < algorithm>
11+ #include < atomic>
12+ #include < condition_variable>
13+ #include < functional>
14+ #include < memory>
15+ #include < mutex>
16+ #include < optional>
17+ #include < ranges>
18+ #include < vector>
19+
20+ #include < boost/container/static_vector.hpp>
21+
22+ namespace ipxp ::output {
23+
24+ class MQ2OutputStorage : public MQOutputStorage {
25+ public:
26+ explicit MQ2OutputStorage (const uint8_t writersCount) noexcept
27+ : MQOutputStorage(writersCount)
28+ {
29+ std::cout << std::endl;
30+ }
31+
32+ bool storeContainer (ContainerWrapper container, const uint8_t writerId) noexcept override
33+ {
34+ BackoffScheme backoff (3 , std::numeric_limits<std::size_t >::max ());
35+ while (!m_queues[writerId].tryWrite (
36+ std::move (container),
37+ *m_allocationBuffer,
38+ m_readerGroupsCount,
39+ std::numeric_limits<std::size_t >::max ())) {
40+ backoff.backoff ();
41+ }
42+ return true ;
43+ }
44+
45+ std::optional<ReferenceCounterHandler<OutputContainer>> getContainer (
46+ const std::size_t readerGroupIndex,
47+ const uint8_t localReaderIndex,
48+ const uint8_t globalReaderIndex) noexcept override
49+ {
50+ const size_t tries = m_totalWritersCount / m_readerGroupSizes[readerGroupIndex] + 1 ;
51+ BackoffScheme backoff (3 , 5 );
52+ for (const auto _ : std::views::iota (0U , tries)) {
53+ const uint8_t sequenceIndex = m_readersData[globalReaderIndex]->sequenceIndex ++;
54+ const uint8_t queueIndex = m_readersData[globalReaderIndex]
55+ ->queueJumpSequence [sequenceIndex % MAX_WRITERS_COUNT ];
56+ ContainerWrapper* container = m_queues[queueIndex].tryRead (readerGroupIndex);
57+ if (container != nullptr ) {
58+ return std::make_optional<ReferenceCounterHandler<OutputContainer>>(
59+ getReferenceCounter (*container));
60+ }
61+ // std::this_thread::yield();
62+ backoff.backoff ();
63+ }
64+ return std::nullopt ;
65+ }
66+
67+ bool finished (const std::size_t readerGroupIndex) noexcept override
68+ {
69+ return m_readerGroupSizes[readerGroupIndex] > m_totalWritersCount
70+ || (!writersPresent () && std::ranges::all_of (m_queues, [&](const Queue& queue) {
71+ return queue.finished ();
72+ }));
73+ }
74+
75+ private:
76+ };
77+
78+ } // namespace ipxp::output
0 commit comments