3#include "spark/patterns/Slot.h"
5#include "spark/mpl/typelist.h"
10namespace spark::patterns
14 template <
typename T,
typename U>
17 static constexpr bool value = std::is_convertible_v<T, U> || std::is_same_v<T, U>;
21 template <
typename... Args>
23 : m_connections(), m_sequence(0) {}
25 template <
typename... Args>
26 Signal<Args...>::Signal(Signal&& signal)
noexcept
31 template <
typename... Args>
32 Signal<Args...>::~Signal()
37 template <
typename... Args>
44 template <
typename... Args>
47 emit(std::forward<Args>(args)...);
50 template <
typename... Args>
53 return connect(slot,
false);
56 template <
typename... Args>
59 return connect(&slot,
false);
62 template <
typename... Args>
68 template <
typename... Args>
74 template <
typename... Args>
80 template <
typename... Args>
83 auto it = std::ranges::find_if(m_connections, [key](
const auto& connection) {
return connection.second.m_slotKey == key; });
84 if (it != m_connections.end())
86 it->second.releaseSlot();
87 m_connections.erase(it);
91 template <
typename... Args>
94 if (slot && slot->
isConnected() && slot->m_connection->m_signal ==
this)
95 disconnect(slot->m_connection->m_slotKey);
98 template <
typename... Args>
104 template <
typename... Args>
107 for (
auto& connection : m_connections | std::views::values)
108 connection.releaseSlot();
109 m_connections.clear();
112 template <
typename... Args>
115 const auto keys = connectedKeys();
116 return std::ranges::find(keys, key) != keys.end();
119 template <
typename... Args>
122 std::vector<std::size_t> keys;
123 keys.reserve(m_connections.size());
124 for (
const auto& connection : m_connections | std::views::values)
125 keys.push_back(connection.m_slotKey);
129 template <
typename... Args>
132 std::vector<
const Slot<Args...>*> slots;
133 for (
const auto& connection : m_connections | std::views::values)
134 slots.push_back(connection.m_slot);
138 template <
typename... Args>
139 template <
typename... FnArgs>
142 if constexpr (
sizeof...(Args) !=
sizeof...(FnArgs))
143 static_assert(
false,
"Signal::emit() called with different number of arguments than the signal.");
144 else if constexpr (
sizeof...(Args) != 0)
146 typename mpl::typelist<FnArgs...>::template transform<std::remove_cvref>,
147 typename mpl::typelist<Args...>::template transform<std::remove_cvref>>,
148 "Cannot call Signal::emit() with args that are not in the signal.");
158 auto keys_view = m_connections | std::views::keys;
159 std::vector<std::size_t> keys = {keys_view.begin(), keys_view.end()};
161 for (
const auto& key : keys)
163 if (m_connections.contains(key))
165 const auto& connection = m_connections.at(key);
166 if (connection.m_slot->m_callback)
167 m_connections.at(key).m_slot->m_callback(std::forward<FnArgs>(args)...);
172 template <
typename... Args>
178 if (slot->m_connection)
180 if (slot->m_connection->m_signal ==
this)
181 return slot->m_connection->m_slotKey;
185 const std::size_t key = ++m_sequence;
186 auto res = m_connections.insert({key - 1, details::Connection(
this, slot, key, managed)});
187 slot->m_connection = &res.first->second;
191 template <
typename... Args>
192 void Signal<Args...>::move(Signal* signal)
195 m_connections = std::move(signal->m_connections);
196 m_sequence = signal->m_sequence;
198 for (
auto& connection : m_connections | std::views::values)
199 connection.m_signal = this;
201 signal->m_sequence = 0;
202 signal->m_connections.clear();
A signal is a class used to emit events.
Definition Slot.h:10
void disconnect(std::size_t key)
Disconnects a slot from the signal.
Definition Signal.h:81
std::vector< std::size_t > connectedKeys() const
Gets all the keys of the connected slots.
Definition Signal.h:120
bool isConnected(std::size_t key) const
Finds if a slot is connected to the signal.
Definition Signal.h:113
std::size_t connect(Slot< Args... > *slot)
Connects a slot to the signal.
Definition Signal.h:51
void clear()
Disconnects all connected slots from the signal.
Definition Signal.h:105
std::vector< const Slot< Args... > * > connectedSlots() const
Gets all the connected slots.
Definition Signal.h:130
void emit(FnArgs &&... args) const
Emits the signal to all connected slots.
Definition Signal.h:140
void operator()(Args &&... args) const
Emits the signal to all connected slots. Same as emit.
Definition Signal.h:45
A slot is a connection between a signal and a callback.
Definition Slot.h:18
bool isConnected() const
Checks if this slot is connected to a signal.
Definition Slot.h:72
void disconnect()
Disconnects this slot from the signal.
Definition Slot.h:78