NcEngine
Signal.h
Go to the documentation of this file.
1
5#pragma once
6
7#include "detail/SignalInternal.h"
8
9#include "ncutility/NcError.h"
10
11#include <algorithm>
12
13namespace nc
14{
22{
23 public:
24 explicit Connection(std::weak_ptr<detail::SharedConnectionState> state) noexcept
25 : m_state{std::move(state)}
26 {
27 }
28
29 ~Connection() noexcept
30 {
31 Disconnect();
32 }
33
34 Connection(Connection&&) = default;
35 Connection& operator=(Connection&&) = default;
36 Connection(const Connection&) = delete;
37 Connection& operator=(const Connection&) = delete;
38
39 bool IsConnected() const noexcept
40 {
41 const auto state = m_state.lock();
42 return state && state->IsConnected();
43 }
44
45 bool Disconnect() noexcept
46 {
47 auto state = m_state.lock();
48 return state && state->Disconnect();
49 }
50
51 private:
52 std::weak_ptr<detail::SharedConnectionState> m_state;
53};
54
57{
58 static constexpr size_t Lowest = 0ull;
59 static constexpr size_t Highest = std::numeric_limits<size_t>::max();
60};
61
63template<class... Args>
64class Signal
65{
66 public:
67 using Slot_t = detail::Slot<Args...>;
68
69 Signal() = default;
70 Signal(Signal&&) = default;
71 Signal& operator=(Signal&&) = default;
72 Signal(const Signal&) = delete;
73 Signal& operator=(const Signal&) = delete;
74
76 [[nodiscard]] auto Connect(std::move_only_function<void(Args...)> func, size_t priority = SignalPriority::Highest) -> Connection
77 {
78 const auto pos = std::ranges::find_if(m_slots, [priority](auto&& slot)
79 {
80 return priority >= slot.Priority();
81 });
82
83 if (pos != m_slots.cend())
84 {
85 auto result = m_slots.emplace(pos, std::move(func), m_link.get(), priority, ++m_currentId);
86 return Connection{result->GetState()};
87 }
88
89 auto& result = m_slots.emplace_back(std::move(func), m_link.get(), priority, ++m_currentId);
90 return Connection{result.GetState()};
91 }
92
94 template<class T>
95 [[nodiscard]] auto Connect(T *inst, void (T::*func)(Args...), size_t priority = SignalPriority::Highest) -> Connection
96 {
97 return Connect([=](Args... args){ (inst->*func)(args...); }, priority);
98 }
99
101 template<class T>
102 [[nodiscard]] auto Connect(const T *inst, void (T::*func)(Args...) const, size_t priority = SignalPriority::Highest) -> Connection
103 {
104 return Connect([=](Args... args){ (inst->*func)(args...); }, priority);
105 }
106
109 {
110 m_slots.clear();
111 m_currentId = 0;
112 m_link->GetPendingDisconnections(); // Don't need Sync() - just discard
113 }
114
116 auto ConnectionCount() const noexcept -> size_t
117 {
118 Sync();
119 return m_slots.size();
120 }
121
123 void Emit(Args... args)
124 {
125 Sync();
126 for (auto& slot : m_slots)
127 {
128 slot(args...);
129 }
130 }
131
133 void operator()(Args... args)
134 {
135 Emit(args...);
136 }
137
138 private:
139 mutable std::unique_ptr<detail::ConnectionBacklink> m_link = std::make_unique<detail::ConnectionBacklink>();
140 mutable std::vector<Slot_t> m_slots{};
141 int m_currentId{0};
142
143 void Sync() const
144 {
145 const auto pendingRemovals = m_link->GetPendingDisconnections();
146 for(const auto id : pendingRemovals)
147 {
148 std::erase_if(m_slots, [id](const auto& state) { return state.Id() == id; });
149 }
150 }
151};
152} // namespace nc
An RAII object managing a Signal connection.
Definition: Signal.h:22
An event source supporting multiple Connections.
Definition: Signal.h:65
void DisconnectAll()
Remove all connections.
Definition: Signal.h:108
auto ConnectionCount() const noexcept -> size_t
Get the number of active connections.
Definition: Signal.h:116
void Emit(Args... args)
Invoke all slots.
Definition: Signal.h:123
auto Connect(std::move_only_function< void(Args...)> func, size_t priority=SignalPriority::Highest) -> Connection
Connect a std::move_only_function.
Definition: Signal.h:76
void operator()(Args... args)
Invoke all slots.
Definition: Signal.h:133
auto Connect(T *inst, void(T::*func)(Args...), size_t priority=SignalPriority::Highest) -> Connection
Connect a member function.
Definition: Signal.h:95
auto Connect(const T *inst, void(T::*func)(Args...) const, size_t priority=SignalPriority::Highest) -> Connection
Connect a const member function.
Definition: Signal.h:102
Definition: SignalInternal.h:84
Priority values for controlling call order from a Signal.
Definition: Signal.h:57