Anklang-0.3.0.dev956+gd75ac925 anklang-0.3.0.dev956+gd75ac925
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
queuemux.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#pragma once
3
4#include <ase/cxxaux.hh>
5
6namespace Ase {
7
11template<size_t MAXQUEUES, class ForwardIterator>
15 using Priority = decltype (QueueMultiplexer_priority (std::declval<const ValueType&>()));
16 struct Ptr { ForwardIterator it, end; };
17 ssize_t n_queues = 0, current = -1;
18 Priority first = {}, next = {};
20 QueueMultiplexer () {}
21 template<class IterableContainer> bool
23 {
24 static_assert (std::is_same<
25 ForwardIterator,
27 >::value);
28 n_queues = 0;
29 for (size_t i = 0; i < queues.size(); i++)
30 if (queues[i]) [[likely]]
31 {
32 ptrs[n_queues].it = std::begin (*queues[i]);
33 ptrs[n_queues].end = std::end (*queues[i]);
34 if (ptrs[n_queues].it != ptrs[n_queues].end)
35 n_queues++;
36 }
37 seek();
38 return more();
39 }
40 size_t
41 count_pending() const noexcept
42 {
43 size_t c = 0;
44 for (ssize_t i = 0; i < n_queues; i++)
45 c += ptrs[i].end - ptrs[i].it;
46 return c;
47 }
48 bool
49 more() const noexcept
50 {
51 return n_queues > 0;
52 }
53 const ValueType&
54 peek () noexcept
55 {
56 if (!more()) [[unlikely]]
57 return empty();
58 return *ptrs[current].it;
59 }
60 const ValueType&
61 pop () noexcept
62 {
63 ASE_ASSERT_RETURN (more(), empty());
64 const ValueType &result = *ptrs[current].it++;
65 if (ptrs[current].it == ptrs[current].end) [[unlikely]]
66 { // remove emptied queue
67 if (current < n_queues - 1) [[unlikely]]
68 ptrs[current] = ptrs[n_queues - 1]; // shuffles queue order, preserves prios
69 n_queues--;
70 seek();
71 }
72 else if (QueueMultiplexer_priority (*ptrs[current].it)
73 > next) [[unlikely]] // next is in other queue
74 seek();
75 return result;
76 }
77 class Iter {
78 QueueMultiplexer *mux_ = nullptr;
79 public:
80 using difference_type = ssize_t;
81 using value_type = const ValueType;
82 using pointer = const value_type*;
83 using reference = const value_type&;
85 /*ctor*/ Iter (QueueMultiplexer *u = nullptr) : mux_ (u && u->more() ? u : nullptr) {}
86 bool more () const { return mux_ && mux_->more(); }
87 friend bool operator== (const Iter &a, const Iter &b) { return a.more() == b.more(); }
88 value_type& operator* () const { return mux_ ? mux_->peek() : empty(); }
89 Iter operator++ (int) { Iter copy (*this); this->operator++(); return copy; }
90 Iter& operator++ ()
91 {
92 if (mux_) [[likely]] {
93 if (mux_->more()) [[likely]]
94 mux_->pop();
95 else
96 mux_ = nullptr;
97 }
98 return *this;
99 }
100 };
101 using iterator = Iter;
102 iterator begin () { return Iter (this); }
103 iterator end () { return {}; }
104private:
105 void
106 seek() noexcept
107 {
108 if (n_queues == 0) [[likely]]
109 return;
110 current = 0; // picks first queue if all contain max Priority
112 first = next; // Priority to start with
113 for (ssize_t i = 0; i < n_queues; i++)
114 {
115 const Priority prio = QueueMultiplexer_priority (*ptrs[i].it);
116 if (prio < first) // prio comes before first
117 {
118 next = first;
119 first = prio;
120 current = i; // pick first matching Queue
121 }
122 else if (prio < next) // found next prio
123 next = prio;
124 }
125 // dprintf (2, "%s: n_queues=%zd current=%zd first=%ld next=%ld\n", __func__, n_queues, current, long (first), long (next));
126 }
127 static const ValueType&
128 empty() noexcept ASE_NOINLINE
129 {
130 static const ValueType empty_ {};
131 return empty_;
132 }
133};
134
135} // Ase
136
T begin(T... args)
#define ASE_ASSERT_RETURN(expr,...)
Return from the current function if expr evaluates to false and issue an assertion warning.
Definition cxxaux.hh:81
T end(T... args)
T max(T... args)
The Anklang C++ API namespace.
Definition api.hh:8
Multiplexer to pop from multiple Queues, while preserving priorities.
Definition queuemux.hh:13
typedef ssize_t