1+ #include " near_events_storage.hpp"
2+
3+ namespace sim {
4+
5+ void NearEventsStorage::add (std::unique_ptr<Event> event, TimeNs current_time) {
6+ std::uint32_t relative_event_time =
7+ (event->get_time () - current_time).value_nanoseconds ();
8+
9+ auto add_to_storage =
10+ [](std::deque<std::queue<std::unique_ptr<Event> > >& storage,
11+ std::size_t index, std::unique_ptr<Event> event) {
12+ if (index >= storage.size ()) {
13+ storage.resize (index + 1 );
14+ }
15+ storage[index].emplace (std::move (event));
16+ };
17+
18+ std::uint32_t first_storage_bucket_index =
19+ m_current_bucket + relative_event_time;
20+ if (first_storage_bucket_index < m_max_buckets_count) {
21+ // its enough place to put event to first bucket; use it
22+ add_to_storage (m_first_event_buckets_storage,
23+ first_storage_bucket_index, std::move (event));
24+ m_first_bucket_empty = false ;
25+ } else {
26+ // event could not be stores in first bucket; put it to second one
27+ add_to_storage (m_second_event_buckets_storage,
28+ first_storage_bucket_index - m_max_buckets_count,
29+ std::move (event));
30+ m_second_bucket_empty = false ;
31+ }
32+ }
33+
34+ std::unique_ptr<Event> NearEventsStorage::pop_first () {
35+ correctify_state ();
36+ // state is correct
37+ if (empty ()) {
38+ throw std::runtime_error (" call from on empty storage" );
39+ }
40+ std::unique_ptr<Event> event =
41+ std::move (m_first_event_buckets_storage[m_current_bucket].front ());
42+ // be careful: after next line state should be correctified (current bucket
43+ // might become empty or all m_first_storage)
44+ m_first_event_buckets_storage[m_current_bucket].pop ();
45+ return event;
46+ }
47+
48+ bool NearEventsStorage::empty () {
49+ correctify_state ();
50+ return m_first_bucket_empty;
51+ }
52+
53+ void NearEventsStorage::correctify_state () {
54+ if (!m_first_bucket_empty) {
55+ while (m_current_bucket < m_first_event_buckets_storage.size () &&
56+ m_first_event_buckets_storage[m_current_bucket].empty ()) {
57+ m_current_bucket++;
58+ }
59+ if (m_current_bucket != m_first_event_buckets_storage.size ()) {
60+ // m_first_event_buckets_storage[m_current_bucket] is not empty ->
61+ // state is correct
62+ return ;
63+ }
64+ }
65+
66+ // all events in first storages are done => first bucket is <<empty>>
67+ m_first_bucket_empty = true ;
68+ m_current_bucket = 0 ;
69+
70+ if (m_second_bucket_empty) {
71+ // second bucket is empty => all buckets are empty
72+ return ;
73+ }
74+
75+ while (m_current_bucket < m_first_event_buckets_storage.size () &&
76+ m_second_event_buckets_storage[m_current_bucket].empty ()) {
77+ m_current_bucket++;
78+ }
79+
80+ // swap storages
81+ m_first_event_buckets_storage.swap (m_second_event_buckets_storage);
82+ std::swap (m_first_bucket_empty, m_second_bucket_empty);
83+ }
84+
85+ } // namespace sim
0 commit comments