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