Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
eventlist.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_EVENTLIST_HH__
3#define __ASE_EVENTLIST_HH__
4
5#include <ase/utils.hh>
6#include <algorithm>
7#include <any>
8
9namespace Ase {
10
12template<class Event, class CompareOrder>
16 explicit OrderedEventList (const std::vector<Event> &ve);
17 const Event* lookup (const Event &event) const;
18 const Event* lookup_after (const Event &event) const;
19private:
20 CompareOrder compare_;
21};
22
24template<class Event, class Compare>
25class EventList final {
27public:
28 using Notify = std::function<void (const Event &event, int mod)>;
29 using CIter = typename EventVector::const_iterator;
30 explicit EventList (const Notify &n = {}, const Compare &c = {});
31 bool insert (const Event &event, Event *replaced = nullptr);
32 bool replace (const Event &event, Event *replaced = nullptr);
33 bool remove (const Event &event, Event *removed = nullptr);
34 const Event* lookup (const Event &event) const;
35 const Event* lookup_after (const Event &event) const;
36 const Event* first () const;
37 const Event* last () const;
38 size_t size () const;
40 template<class OrderedEventList> typename OrderedEventList::ConstP
41 inline ordered_events ();
42 CIter begin () const { return events_.begin(); }
43 CIter end () const { return events_.end(); }
44 EventVector copy () const { return events_; }
45 bool equals (const EventVector &ev) const { return ev == events_; }
46private:
47 EventVector events_;
48 Compare compare_;
49 Notify notify_;
50 std::any ordered_;
51 static_assert (std::is_signed<decltype (std::declval<Compare>() (std::declval<Event>(), std::declval<Event>()))>::value, "REQUIRE: int Compare (const&, const&);");
52 void uncache ();
53 static void nop (const Event&, int) {}
54};
55
56// == Implementation Details ==
57template<class Event, class Compare> inline
58EventList<Event,Compare>::EventList (const Notify &n, const Compare &c) :
59 compare_ (c), notify_ (n)
60{
61 if (!notify_)
62 notify_ = nop;
63}
64
65template<class Event, class Compare> inline void
67{
68 events_.clear();
69 ordered_.reset();
70}
71
72template<class Event, class Compare> inline void
74{
75 ordered_.reset();
76}
77
78template<class Event, class Compare> inline bool
79EventList<Event,Compare>::insert (const Event &event, Event *replaced)
80{
81 uncache();
82 if (events_.size() && compare_ (event, events_.back()) > 0)
83 {
84 events_.push_back (event);
85 notify_ (event, +1); // notify insertion
86 return false; // O(1) fast path for append
87 }
88 auto insmatch = Aux::binary_lookup_insertion_pos (events_.begin(), events_.end(), compare_, event);
89 auto it = insmatch.first;
90 if (insmatch.second == true) // exact match
91 {
92 if (replaced)
93 *replaced = *it;
94 *it = event;
95 notify_ (event, 0); // notify change
96 return true;
97 }
98 else
99 {
100 events_.insert (it, event);
101 notify_ (event, +1); // notify insertion
102 return false;
103 }
104}
105
106template<class Event, class Compare> inline bool
108{
109 auto insmatch = Aux::binary_lookup_insertion_pos (events_.begin(), events_.end(), compare_, event);
110 if (insmatch.second == true) // exact match
111 {
112 uncache();
113 auto it = insmatch.first;
114 if (replaced)
115 *replaced = *it;
116 *it = event;
117 notify_ (event, 0); // notify change
118 return true;
119 }
120 return false;
121}
122
123template<class Event, class Compare> inline bool
125{
126 uncache();
127 const int cmp = events_.empty() ? +1 : compare_ (event, events_.back());
128 if (cmp == 0)
129 {
130 if (removed)
131 *removed = events_.back();
132 events_.pop_back(); // O(1) fast path for tail removal
133 notify_ (event, -1); // notify removal
134 return true; // found and removed
135 }
136 if (cmp < 0)
137 {
138 auto it = Aux::binary_lookup (events_.begin(), events_.end() - 1, compare_, event);
139 if (it != events_.end())
140 {
141 if (removed)
142 *removed = *it;
143 events_.erase (it);
144 notify_ (event, -1); // notify removal
145 return true; // found and removed
146 }
147 }
148 return false; // none removed
149}
150
151template<class Event, class Compare> inline const Event*
153{
154 return events_.empty() ? nullptr : &events_.front();
155}
156
157template<class Event, class Compare> inline const Event*
159{
160 return events_.empty() ? nullptr : &events_.back();
161}
162
163template<class Event, class Compare> inline size_t
165{
166 return events_.size();
167}
168
169template<class Event, class Compare> inline const Event*
171{
172 auto it = Aux::binary_lookup (events_.begin(), events_.end(), compare_, event);
173 return it != events_.end() ? &*it : nullptr;
174}
175
176template<class Event, class Compare> inline const Event*
178{
179 auto it = Aux::binary_lookup_insertion_pos (events_.begin(), events_.end(), compare_, event).first;
180 return it != events_.end() ? &*it : nullptr;
181}
182
183template<class Event, class Compare>
184template<class OrderedEventList> inline typename OrderedEventList::ConstP
186{
187 using OrderedEventListP = typename OrderedEventList::ConstP;
188 OrderedEventListP *oepp = std::any_cast<OrderedEventListP> (&ordered_);
189 if (!oepp)
190 {
191 ordered_ = std::make_shared<const OrderedEventList> (events_);
192 oepp = std::any_cast<OrderedEventListP> (&ordered_);
193 ASE_ASSERT_RETURN (oepp, nullptr);
194 }
195 return *oepp;
196}
197
198template<class Event, class CompareOrder>
200 Base (ve)
201{
202 auto lesser = [this] (const Event &a, const Event &b) {
203 return compare_ (a, b) < 0;
204 };
205 std::stable_sort (this->begin(), this->end(), lesser);
206}
207
208template<class Event, class CompareOrder> inline const Event*
209OrderedEventList<Event,CompareOrder>::lookup (const Event &event) const
210{
211 auto it = Aux::binary_lookup (this->begin(), this->end(), compare_, event);
212 return it != this->end() ? &*it : nullptr;
213}
214
215template<class Event, class CompareOrder> inline const Event*
216OrderedEventList<Event,CompareOrder>::lookup_after (const Event &event) const
217{
218 auto it = Aux::binary_lookup_insertion_pos (this->begin(), this->end(), compare_, event).first;
219 return it != this->end() ? &*it : nullptr;
220}
221
222} // Ase
223
224#endif // __ASE_EVENTLIST_HH__
T back(T... args)
T begin(T... args)
Maintain an array of unique Event structures with change notification.
Definition eventlist.hh:25
bool remove(const Event &event, Event *removed=nullptr)
Only replace event, notifies.
Definition eventlist.hh:124
CIter end() const
Const iterator that points to the first element.
Definition eventlist.hh:43
void clear_silently()
Return the numberof elements.
Definition eventlist.hh:66
OrderedEventList::ConstP ordered_events()
Clear list without notification.
Definition eventlist.hh:185
bool replace(const Event &event, Event *replaced=nullptr)
Insert or replace event, notifies.
Definition eventlist.hh:107
CIter begin() const
Create a read-only copy of this EventList (possibly cached).
Definition eventlist.hh:42
const Event * lookup(const Event &event) const
Return true if event was removed, notifies.
Definition eventlist.hh:170
size_t size() const
Return last element or nullptr.
Definition eventlist.hh:164
EventVector copy() const
Const iterator that points one past the last element.
Definition eventlist.hh:44
const Event * lookup_after(const Event &event) const
Return pointer to matching event or nullptr.
Definition eventlist.hh:177
const Event * first() const
Return pointer to element that is >= event or nullptr.
Definition eventlist.hh:152
const Event * last() const
Return first element or nullptr.
Definition eventlist.hh:158
#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 empty(T... args)
T end(T... args)
T erase(T... args)
RandIter binary_lookup(RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
Definition utils.hh:313
std::pair< RandIter, bool > binary_lookup_insertion_pos(RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
Definition utils.hh:289
The Anklang C++ API namespace.
Definition api.hh:9
T stable_sort(T... args)
Structure for callback based notifications.
Definition value.hh:113
Container for a sorted array of opaque Event structures with binary lookup.
Definition eventlist.hh:13