|
20 | 20 | #include <rpp/utils/utils.hpp>
|
21 | 21 |
|
22 | 22 | #include <algorithm>
|
23 |
| -#include <deque> |
| 23 | +#include <list> |
24 | 24 | #include <memory>
|
25 | 25 | #include <mutex>
|
26 | 26 | #include <variant>
|
@@ -67,7 +67,7 @@ namespace rpp::subjects::details
|
67 | 67 | };
|
68 | 68 |
|
69 | 69 | using observer = std::shared_ptr<rpp::details::observers::observer_vtable<Type>>;
|
70 |
| - using observers = std::deque<observer>; |
| 70 | + using observers = std::list<observer>; |
71 | 71 | using shared_observers = std::shared_ptr<observers>;
|
72 | 72 | using state_t = std::variant<shared_observers, std::exception_ptr, completed, disposed>;
|
73 | 73 |
|
@@ -112,22 +112,21 @@ namespace rpp::subjects::details
|
112 | 112 | void on_next(const Type& v)
|
113 | 113 | {
|
114 | 114 | std::unique_lock observers_lock{m_mutex};
|
| 115 | + process_state_unsafe(m_state, [&](shared_observers observers) { |
| 116 | + if (!observers) |
| 117 | + return; |
115 | 118 |
|
116 |
| - if (!std::holds_alternative<shared_observers>(m_state)) |
117 |
| - return; |
| 119 | + auto itr = observers->cbegin(); |
| 120 | + const auto size = observers->size(); |
118 | 121 |
|
119 |
| - // we are getting copy of curent deque and obtaining CURRENT begin/end of in case of some new observer would be added during on_next call |
120 |
| - const auto observers = std::get<shared_observers>(m_state); |
121 |
| - if (!observers) |
122 |
| - return; |
| 122 | + observers_lock.unlock(); |
123 | 123 |
|
124 |
| - const auto begin = observers->cbegin(); |
125 |
| - const auto end = observers->cend(); |
126 |
| - |
127 |
| - observers_lock.unlock(); |
128 |
| - |
129 |
| - std::lock_guard lock{m_serialized_mutex}; |
130 |
| - std::for_each(begin, end, [&](const observer& obs) { obs->on_next(v); }); |
| 124 | + std::lock_guard lock{m_serialized_mutex}; |
| 125 | + for (size_t i = 0; i < size; ++i) |
| 126 | + { |
| 127 | + (*(itr++))->on_next(v); |
| 128 | + } |
| 129 | + }); |
131 | 130 | }
|
132 | 131 |
|
133 | 132 | void on_error(const std::exception_ptr& err)
|
@@ -171,19 +170,18 @@ namespace rpp::subjects::details
|
171 | 170 | return subs;
|
172 | 171 | }
|
173 | 172 |
|
174 |
| - static void process_state_unsafe(const state_t& state, const auto&... actions) |
| 173 | + static auto process_state_unsafe(const state_t& state, const auto&... actions) |
175 | 174 | {
|
176 |
| - std::visit(rpp::utils::overloaded{actions..., rpp::utils::empty_function_any_t{}}, state); |
| 175 | + return std::visit(rpp::utils::overloaded{actions..., rpp::utils::empty_function_any_t{}}, state); |
177 | 176 | }
|
178 | 177 |
|
179 | 178 | shared_observers exchange_observers_under_lock_if_there(state_t&& new_val)
|
180 | 179 | {
|
181 | 180 | std::lock_guard lock{m_mutex};
|
182 | 181 |
|
183 |
| - if (!std::holds_alternative<shared_observers>(m_state)) |
184 |
| - return {}; |
185 |
| - |
186 |
| - return std::get<shared_observers>(std::exchange(m_state, std::move(new_val))); |
| 182 | + return process_state_unsafe(m_state, [&](shared_observers observers) { |
| 183 | + m_state = std::move(new_val); |
| 184 | + return observers; }, [](auto) { return shared_observers{}; }); |
187 | 185 | }
|
188 | 186 |
|
189 | 187 | private:
|
|
0 commit comments