5 # ifndef VCCC_SIGNAL_SIGNAL_H_
6 # define VCCC_SIGNAL_SIGNAL_H_
11 # include <type_traits>
28 template<
typename R,
typename ...Args,
typename Group>
29 class signal_impl<R(Args...), Group> :
30 public std::enable_shared_from_this<signal_impl<R(Args...), Group>> {
32 using is_void_return_type =
typename std::is_void<R>::type;
33 using void_return_type = std::true_type;
34 using not_void_return_type = std::false_type;
37 using slot_type = slot<R(Args...)>;
38 using group_type = Group;
40 using slot_list_type = grouped_slot_list<group_type, slot_type>;
41 using group_key_type =
typename slot_list_type::group_key_type;
42 using weak_slot =
typename slot_list_type::weak_slot;
43 using weak_slot_list =
typename slot_list_type::weak_slot_list;
44 using weak_iterator =
typename weak_slot_list::iterator;
45 using token_type =
typename slot_list_type::insert_token;
46 using connection_body = connection_impl<signal_impl<R(Args...), Group>, weak_slot>;
48 friend connection_body;
51 arity =
sizeof...(Args),
55 : slot_list_(
std::make_shared<slot_list_type>()) {}
57 connection connect(
const slot_type& slot,
slot_position pos) {
58 std::lock_guard<std::mutex> lck(slot_mutex_);
60 std::shared_ptr<connection_impl_base> new_connection
61 = make_new_connection(slot_list_->insert(std::make_shared<slot_type>(slot), pos));
65 return connection(std::move(new_connection));
68 connection connect(group_type group,
const slot_type& slot,
slot_position pos) {
69 std::lock_guard<std::mutex> lck(slot_mutex_);
71 std::shared_ptr<connection_impl_base> new_connection
72 = make_new_connection(slot_list_->insert(group, std::make_shared<slot_type>(slot), pos));
76 return connection(new_connection);
87 void disconnect(group_type group) {
88 std::lock_guard<std::mutex> lck(slot_mutex_);
90 group_key_type group_key(
grouped, group);
91 slot_list_->remove_group(group_key);
98 std::lock_guard<std::mutex> lck(slot_mutex_);
99 group_key_type group_key(category);
100 slot_list_->remove_group(group_key);
103 void disconnect_all() {
104 std::lock_guard<std::mutex> lck(slot_mutex_);
105 slot_list_->remove_all();
109 return slot_list_->size();
112 template<
typename ...U>
113 return_type operator()(U&&... args) {
114 return invoke(is_void_return_type<return_type>{}, std::forward<U>(args)...);
117 template<
typename ...U>
118 return_type operator()(U&&... args)
const {
119 return invoke(is_void_return_type<return_type>{}, std::forward<U>(args)...);
124 void disconnect(
const token_type &token) {
125 std::lock_guard<std::mutex> lck(slot_mutex_);
126 slot_list_->remove(token);
129 void set_track(connection*, token_type* token, std::weak_ptr<void> target) {
130 std::lock_guard<std::mutex> lck(slot_mutex_);
131 auto& slot_ptr = (*(token->second));
132 slot_ptr->track(std::move(target));
135 std::shared_ptr<connection_body> make_new_connection(weak_slot&& slot) {
136 return std::make_shared<connection_body>(this->shared_from_this(), std::move(slot));
139 template<
typename ...U>
140 void invoke(void_return_type, U&&... args)
const {
141 weak_slot_list weak_slots;
143 std::lock_guard<std::mutex> lck(slot_mutex_);
144 weak_slots = slot_list_->getWeakList();
146 for (
const auto& weak_slot : weak_slots) {
147 auto locked_slot = weak_slot.first.lock();
148 if (locked_slot ==
nullptr)
150 auto track_lock = locked_slot->lock();
151 if (locked_slot->expired()) {
152 std::lock_guard<std::mutex> lck(slot_mutex_);
153 slot_list_->remove(weak_slot.second);
156 (*locked_slot)(args...);
160 template<
typename ...U>
161 return_type
invoke(not_void_return_type, U&&... args)
const {
162 weak_slot_list weak_slots;
164 std::lock_guard<std::mutex> lck(slot_mutex_);
165 weak_slots = slot_list_->getWeakList();
168 for (
const auto& weak_slot : weak_slots) {
169 auto locked_slot = weak_slot.first.lock();
170 if (locked_slot ==
nullptr)
172 auto track_lock = locked_slot->lock();
173 if (locked_slot->expired()) {
174 std::lock_guard<std::mutex> lck(slot_mutex_);
175 slot_list_->remove(weak_slot.second);
178 result = (*locked_slot)(args...);
183 mutable std::shared_ptr<slot_list_type> slot_list_;
184 mutable std::mutex slot_mutex_;
196 template<
typename R,
typename ...Args,
typename Group>
205 : pimpl_(
std::make_shared<
impl>()) {}
208 return pimpl_->connect(
slot, pos);
212 return pimpl_->connect(group,
slot, pos);
224 return pimpl_->disconnect(group);
228 return pimpl_->disconnect(group_cat);
232 return pimpl_->disconnect_all();
236 return pimpl_->size();
239 template<
typename ...U>
241 return (*pimpl_)(std::forward<U>(args)...);
244 template<
typename ...U>
246 return (*pimpl_)(std::forward<U>(args)...);
250 std::shared_ptr<impl> pimpl_;
Connection manager for a single slot.
Definition: connection.h:83
a wrapper that may or may not hold an object
Definition: optional.h:46
void disconnect_all()
Definition: signal.h:231
auto size() const
Definition: signal.h:235
signal()
Definition: signal.h:204
return_type operator()(U &&... args)
Definition: signal.h:240
connection connect(group_type group, const slot_type &slot, slot_position pos=at_back)
Definition: signal.h:211
void disconnect(group_category group_cat)
Definition: signal.h:227
typename impl::return_type return_type
Definition: signal.h:202
return_type operator()(U &&... args) const
Definition: signal.h:245
Group group_type
Definition: signal.h:201
void disconnect(group_type group)
Definition: signal.h:223
connection connect(const slot_type &slot, slot_position pos=at_back)
Definition: signal.h:207
typename impl::slot_type slot_type
Definition: signal.h:200
Definition: forward_declare.h:13
Definition: forward_declare.h:16
constexpr invoke_result_t< F, Args... > invoke(F &&f, Args &&... args) noexcept(is_nothrow_invocable< F, Args... >::value)
Definition: invoke.hpp:38
Definition: matrix.hpp:495
Definition: directory.h:12
constexpr auto size(const C &c) -> decltype(c.size())
Definition: size.hpp:16
group_category
Definition: group_key.h:14
@ grouped
Definition: group_key.h:14
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
slot_position
Definition: slot_group.h:21
@ at_back
Definition: slot_group.h:22