Toast Engine
Loading...
Searching...
No Matches
signals.hpp
Go to the documentation of this file.
1
6
7#pragma once
8
9#pragma once
10
11#include "signal_types.hpp"
12#include "toast/uid.hpp"
13#include "toast/world/box.hpp"
14
15#include <algorithm>
16#include <any>
17#include <functional>
18#include <memory>
19#include <mutex>
20#include <span>
21#include <string>
22#include <string_view>
23#include <tuple>
24#include <type_traits>
25#include <utility>
26#include <vector>
27
28namespace toast {
29class Node;
30}
31
32namespace signals {
33
34template<typename... Args>
35class Signal {
36 static_assert(sizeof...(Args) <= 4, "signals::Signal supports at most four arguments");
37
38 using callback_t = std::function<void(Args...)>;
39
40 struct Connection {
41 toast::UID uid;
42 std::string identifier;
43 ConnectionSource source = ConnectionSource::unknown;
44 bool forwards_args = true;
45
46 toast::Box<toast::Node> node;
47 callback_t cb;
48 };
49
50 using ConnectionList = std::vector<Connection>;
51
57 mutable std::mutex m_mutex;
58 std::shared_ptr<const ConnectionList> m_connections = std::make_shared<const ConnectionList>();
59
60 [[nodiscard]]
61 auto snapshot() const -> std::shared_ptr<const ConnectionList> {
62 std::scoped_lock lock(m_mutex);
63 return m_connections;
64 }
65
66 template<typename Edit>
67 void modify(Edit&& edit) {
68 std::scoped_lock lock(m_mutex);
69 auto copy = std::make_shared<ConnectionList>(*m_connections);
70 edit(*copy);
71 m_connections = std::move(copy);
72 }
73
74public:
75 Signal() = default;
76
77 Signal(const Signal& other) : m_connections(other.snapshot()) { }
78
79 Signal(Signal&& other) noexcept : m_connections(other.snapshot()) { }
80
81 auto operator=(const Signal& other) -> Signal& {
82 if (this != &other) {
83 auto other_connections = other.snapshot();
84 std::scoped_lock lock(m_mutex);
85 m_connections = std::move(other_connections);
86 }
87 return *this;
88 }
89
90 auto operator=(Signal&& other) noexcept -> Signal& { return *this = other; }
91
92 ~Signal() = default;
93
94 template<typename F>
95 requires(std::is_invocable_r_v<void, F, Args...> || std::is_invocable_r_v<void, F>)
96 void connect(toast::Node& node, F&& cb);
97
98 void connect(
99 toast::Node& node, std::string_view identifier, ConnectionSource source = ConnectionSource::cpp, bool forwards_args = true
100 );
101
102 void disconnect(toast::Node& node, std::string_view identifier, ConnectionSource source = ConnectionSource::cpp);
103
104 void clear(ConnectionSource source);
105
106 [[nodiscard]]
107 auto connections() const -> std::vector<ConnectionInfo>;
108
109 void fire(const Args&... args);
110
111 template<typename NodeType, auto MemberPtr>
112 static auto get(void* signal) -> std::vector<ConnectionInfo>;
113
114 template<typename NodeType, auto MemberPtr>
115 static void
116 connect(void* signal, toast::Node& target, std::string_view identifier, ConnectionSource source, bool forwards_args);
117
118 template<typename NodeType, auto MemberPtr>
119 static void disconnect(void* signal, toast::Node& target, std::string_view identifier, ConnectionSource source);
120
121 template<typename NodeType, auto MemberPtr>
122 static void clear(void* signal, ConnectionSource source);
123
124 template<typename NodeType, auto MemberPtr>
125 static auto fire(void* signal, std::span<const std::any> args) -> bool;
126};
127
128}
129#ifndef NODEFILE
130#include <toast/events/signals.inl>
131#endif
pseudo shared pointer for Nodes
Definition node.hpp:81
Unique identifier for everything that exists in our engine.