sandbox
Loading...
Searching...
No Matches
slot.hpp
1#ifndef LIBSBX_SIGNAL_SLOT_HPP_
2#define LIBSBX_SIGNAL_SLOT_HPP_
3
4#include <type_traits>
5#include <memory>
6#include <functional>
7
8#include <libsbx/signals/cleanable.hpp>
9#include <libsbx/signals/function_traits.hpp>
10#include <libsbx/signals/object_ptr.hpp>
11
12namespace sbx::signals {
13
14template <typename...>
15class slot_base;
16
17template <typename... Args>
18using slot_ptr = std::shared_ptr<slot_base<Args...>>;
19
20template<typename... Args>
21class slot_base : public slot_state {
22
23 template<lockable, typename...>
24 friend class signal_base;
25
26public:
27
28 explicit slot_base(cleanable& cleaner, group_id group)
29 : slot_state{group},
30 _cleaner{cleaner} { }
31
32 ~slot_base() override = default;
33
34 virtual auto call_slot(Args&&...) -> void = 0;
35
36 template<typename... Others>
37 void operator()(Others&&... args) {
38 if (slot_state::is_connected() && !slot_state::is_blocked()) {
39 call_slot(std::forward<Others>(args)...);
40 }
41 }
42
43 template<typename Callable>
44 bool has_callable(const Callable& callable) const {
45 auto handle = get_callable();
46 return eq_function_ptr(callable, handle);
47 }
48
49 template<typename Callable>
51 auto has_full_callable([[maybe_unused]] const Callable& callable) const -> bool {
52 return false;
53 }
54
55 template<typename Callable>
57 auto has_full_callable(const Callable& callable) const -> bool {
58 return has_callable(callable);
59 }
60
61 template<typename Object>
62 bool has_object(const Object& object) const {
63 return get_object() == get_object_ptr(object);
64 }
65
66protected:
67
68 void do_disconnect() final {
69 _cleaner.clean(this);
70 }
71
72 virtual auto get_object() const noexcept -> object_ptr {
73 return nullptr;
74 }
75
76 virtual auto get_callable() const noexcept -> function_ptr {
77 return get_function_ptr(nullptr);
78 }
79
80private:
81
82 cleanable& _cleaner;
83
84}; // class slot_base
85
86template<typename Function, typename... Args>
87class slot final : public slot_base<Args...> {
88
89public:
90
91 template<typename Other, typename Group>
92 constexpr slot(cleanable& cleaner, Other&& other, Group group)
93 : slot_base<Args...>{cleaner, group},
94 _function{std::forward<Other>(other)} { }
95
96protected:
97
98 auto call_slot(Args&&... args) -> void override {
99 std::invoke(_function, std::forward<Args>(args)...);
100 }
101
102 auto get_callable() const noexcept -> function_ptr override {
103 return get_function_ptr(_function);
104 }
105
106private:
107
108 std::decay_t<Function> _function;
109
110}; // class slot
111
112template<typename MemberFunctionPtr, typename Object, typename... Args>
113class member_function_ptr_slot final : public slot_base<Args...> {
114public:
115
116 template<typename MFP, typename O>
117 constexpr member_function_ptr_slot(cleanable& cleanable, MFP&& member_function_ptr, O&& object, group_id group)
118 : slot_base<Args...>{cleanable, group},
119 _member_function_ptr{std::forward<MFP>(member_function_ptr)},
120 _object{std::forward<O>(object)} { }
121
122protected:
123
124 auto call_slot(Args&&... args) -> void override {
125 // ((*_object).*pmf)(args...);
126 std::invoke(_member_function_ptr, _object, std::forward<Args>(args)...);
127 }
128
129 auto get_callable() const noexcept -> function_ptr override {
130 return get_function_ptr(_member_function_ptr);
131 }
132
133 auto get_object() const noexcept -> object_ptr override {
134 return get_object_ptr(_member_function_ptr);
135 }
136
137private:
138
139 std::decay_t<MemberFunctionPtr> _member_function_ptr;
140 std::decay_t<Object> _object;
141
142}; // member_function_ptr_slot
143
144template<typename Function, typename WeakPtr, typename... Args>
145class tracked_slot final : public slot_base<Args...> {
146public:
147
148 template<typename F, typename P>
149 constexpr tracked_slot(cleanable& cleanable, F&& function, P&& object, group_id group)
150 : slot_base<Args...>{cleanable, group},
151 _function{std::forward<F>(function)},
152 _object{std::forward<P>(object)} { }
153
154 auto is_connected() const noexcept -> bool override {
155 return !_object.expired() && slot_state::is_connected();
156 }
157
158protected:
159
160 auto call_slot(Args&&... args) -> void override {
161 auto object = _object.lock();
162
163 if (!object) {
164 slot_state::disconnect();
165 return;
166 }
167
168 if (slot_state::is_connected()) {
169 // func(args...);
170 std::invoke(_function, std::forward<Args>(args)...);
171 }
172 }
173
174 auto get_callable() const noexcept -> function_ptr override {
175 return get_function_ptr(_function);
176 }
177
178 auto get_object() const noexcept -> object_ptr override {
179 return get_object_ptr(_object);
180 }
181
182private:
183
184 std::decay_t<Function> _function;
185 std::decay_t<WeakPtr> _object;
186
187}; // tracked_slot
188
189template<typename MemberFunctionPtr, typename WeakPtr, typename... Args>
190class tracked_member_function_ptr_slot final : public slot_base<Args...> {
191public:
192
193 template<typename MFP, typename O>
194 constexpr tracked_member_function_ptr_slot(cleanable& cleanable, MFP&& member_function_ptr, O&& object, group_id group)
195 : slot_base<Args...>{cleanable, group},
196 _member_function_ptr{std::forward<MFP>(member_function_ptr)},
197 _object{std::forward<O>(object)} { }
198
199 auto is_connected() const noexcept -> bool override {
200 return !_object.expired() && slot_state::is_connected();
201 }
202
203protected:
204
205 auto call_slot(Args&&... args) -> void override {
206 auto object = _object.lock();
207
208 if (!object) {
209 slot_state::disconnect();
210 return;
211 }
212
213 if (slot_state::is_connected()) {
214 // ((*sp).*pmf)(args...);
215 std::invoke(_member_function_ptr, *_object, std::forward<Args>(args)...);
216 }
217 }
218
219 auto get_callable() const noexcept -> function_ptr override {
220 return get_function_ptr(_member_function_ptr);
221 }
222
223 auto get_object() const noexcept -> object_ptr override {
224 return get_object_ptr(_member_function_ptr);
225 }
226
227private:
228
229 std::decay_t<MemberFunctionPtr> _member_function_ptr;
230 std::decay_t<WeakPtr> _object;
231
232}; // tracked_member_function_ptr_slot
233
234} // namespace sbx::signals
235
236#endif // LIBSBX_SIGNAL_SLOT_HPP_
Definition: function_traits.hpp:32
Definition: signal.hpp:16
Definition: slot.hpp:21
Definition: slot_state.hpp:14
Definition: slot.hpp:87
Definition: slot.hpp:145
Definition: cleanable.hpp:10
Definition: function_traits.hpp:74