Anklang 0.3.0-460-gc4ef46ba
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#ifndef __ASE_QUEUEMUX_HH__
3#define __ASE_QUEUEMUX_HH__
4
5#include <ase/cxxaux.hh>
6
7namespace Ase {
8
12template<size_t MAXQUEUES, class ForwardIterator>
16 using Priority = decltype (QueueMultiplexer_priority (std::declval<const ValueType&>()));
17 struct Ptr { ForwardIterator it, end; };
18 ssize_t n_queues = 0, current = -1;
19 Priority first = {}, next = {};
21 QueueMultiplexer () {}
22 template<class IterableContainer> bool
24 {
25 static_assert (std::is_same<
26 ForwardIterator,
28 >::value);
29 n_queues = 0;
30 for (size_t i = 0; i < queues.size(); i++)
31 if (queues[i]) [[likely]]
32 {
33 ptrs[n_queues].it = std::begin (*queues[i]);
34 ptrs[n_queues].end = std::end (*queues[i]);
35 if (ptrs[n_queues].it != ptrs[n_queues].end)
36 n_queues++;
37 }
38 seek();
39 return more();
40 }
41 size_t
42 count_pending() const noexcept
43 {
44 size_t c = 0;
45 for (ssize_t i = 0; i < n_queues; i++)
46 c += ptrs[i].end - ptrs[i].it;
47 return c;
48 }
49 bool
50 more() const noexcept
51 {
52 return n_queues > 0;
53 }
54 const ValueType&
55 peek () noexcept
56 {
57 if (!more()) [[unlikely]]
58 return empty();
59 return *ptrs[current].it;
60 }
61 const ValueType&
62 pop () noexcept
63 {
64 ASE_ASSERT_RETURN (more(), empty());
65 const ValueType &result = *ptrs[current].it++;
66 if (ptrs[current].it == ptrs[current].end) [[unlikely]]
67 { // remove emptied queue
68 if (current < n_queues - 1) [[unlikely]]
69 ptrs[current] = ptrs[n_queues - 1]; // shuffles queue order, preserves prios
70 n_queues--;
71 seek();
72 }
73 else if (QueueMultiplexer_priority (*ptrs[current].it)
74 > next) [[unlikely]] // next is in other queue
75 seek();
76 return result;
77 }
78 class Iter {
79 QueueMultiplexer *mux_ = nullptr;
80 public:
81 using difference_type = ssize_t;
82 using value_type = const ValueType;
83 using pointer = const value_type*;
84 using reference = const value_type&;
86 /*ctor*/ Iter (QueueMultiplexer *u = nullptr) : mux_ (u && u->more() ? u : nullptr) {}
87 bool more () const { return mux_ && mux_->more(); }
88 friend bool operator== (const Iter &a, const Iter &b) { return a.more() == b.more(); }
89 value_type& operator* () const { return mux_ ? mux_->peek() : empty(); }
90 Iter operator++ (int) { Iter copy (*this); this->operator++(); return copy; }
91 Iter& operator++ ()
92 {
93 if (mux_) [[likely]] {
94 if (mux_->more()) [[likely]]
95 mux_->pop();
96 else
97 mux_ = nullptr;
98 }
99 return *this;
100 }
101 };
102 using iterator = Iter;
103 iterator begin () { return Iter (this); }
104 iterator end () { return {}; }
105private:
106 void
107 seek() noexcept
108 {
109 if (n_queues == 0) [[likely]]
110 return;
111 current = 0; // picks first queue if all contain max Priority
113 first = next; // Priority to start with
114 for (ssize_t i = 0; i < n_queues; i++)
115 {
116 const Priority prio = QueueMultiplexer_priority (*ptrs[i].it);
117 if (prio < first) // prio comes before first
118 {
119 next = first;
120 first = prio;
121 current = i; // pick first matching Queue
122 }
123 else if (prio < next) // found next prio
124 next = prio;
125 }
126 // dprintf (2, "%s: n_queues=%zd current=%zd first=%ld next=%ld\n", __func__, n_queues, current, long (first), long (next));
127 }
128 static const ValueType&
129 empty() noexcept ASE_NOINLINE
130 {
131 static const ValueType empty_ {};
132 return empty_;
133 }
134};
135
136} // Ase
137
138#endif /* __ASE_QUEUEMUX_HH__ */
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:82
T end(T... args)
T max(T... args)
The Anklang C++ API namespace.
Definition api.hh:9
typedef ssize_t