VCCC  2024.05
VisualCamp Common C++ library
signal.h
Go to the documentation of this file.
1 # /*
2 # * Created by YongGyu Lee on 2021/06/03.
3 # */
4 #
5 # ifndef VCCC_SIGNAL_SIGNAL_H_
6 # define VCCC_SIGNAL_SIGNAL_H_
7 #
8 # include <functional>
9 # include <memory>
10 # include <mutex>
11 # include <type_traits>
12 # include <utility>
13 #
16 # include "vccc/__signal/slot.h"
18 #
19 # include "vccc/optional.hpp"
20 
21 namespace vccc {
22 
25 
27 
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>> {
31  template<typename T>
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;
35 
36  public:
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>;
47 
48  friend connection_body;
49 
50  enum {
51  arity = sizeof...(Args),
52  };
53 
54  signal_impl()
55  : slot_list_(std::make_shared<slot_list_type>()) {}
56 
57  connection connect(const slot_type& slot, slot_position pos) {
58  std::lock_guard<std::mutex> lck(slot_mutex_);
59 
60  std::shared_ptr<connection_impl_base> new_connection
61  = make_new_connection(slot_list_->insert(std::make_shared<slot_type>(slot), pos));
62 
63 // connection conn(new_connection);
64 // slot.autoDisconnectIfTracking(conn);
65  return connection(std::move(new_connection));
66  }
67 
68  connection connect(group_type group, const slot_type& slot, slot_position pos) {
69  std::lock_guard<std::mutex> lck(slot_mutex_);
70 
71  std::shared_ptr<connection_impl_base> new_connection
72  = make_new_connection(slot_list_->insert(group, std::make_shared<slot_type>(slot), pos));
73 
74 // connection conn(new_connection);
75 // slot.autoDisconnectIfTracking(conn);
76  return connection(new_connection);
77  }
78 
79 // void disconnect(connection& conn) const {
80 // conn.disconnect();
81 // }
82 //
83 // void disconnect(connection& conn) {
84 // conn.disconnect();
85 // }
86 
87  void disconnect(group_type group) {
88  std::lock_guard<std::mutex> lck(slot_mutex_);
89 
90  group_key_type group_key(grouped, group);
91  slot_list_->remove_group(group_key);
92  }
93 
94  void disconnect(group_category category) {
95  if (category == grouped)
96  return;
97 
98  std::lock_guard<std::mutex> lck(slot_mutex_);
99  group_key_type group_key(category);
100  slot_list_->remove_group(group_key);
101  }
102 
103  void disconnect_all() {
104  std::lock_guard<std::mutex> lck(slot_mutex_);
105  slot_list_->remove_all();
106  }
107 
108  auto size() const {
109  return slot_list_->size();
110  }
111 
112  template<typename ...U>
113  return_type operator()(U&&... args) {
114  return invoke(is_void_return_type<return_type>{}, std::forward<U>(args)...);
115  }
116 
117  template<typename ...U>
118  return_type operator()(U&&... args) const {
119  return invoke(is_void_return_type<return_type>{}, std::forward<U>(args)...);
120  }
121 
122  private:
123 
124  void disconnect(const token_type &token) {
125  std::lock_guard<std::mutex> lck(slot_mutex_);
126  slot_list_->remove(token);
127  }
128 
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));
133  }
134 
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));
137  }
138 
139  template<typename ...U>
140  void invoke(void_return_type, U&&... args) const {
141  weak_slot_list weak_slots;
142  {
143  std::lock_guard<std::mutex> lck(slot_mutex_);
144  weak_slots = slot_list_->getWeakList();
145  }
146  for (const auto& weak_slot : weak_slots) {
147  auto locked_slot = weak_slot.first.lock();
148  if (locked_slot == nullptr)
149  continue;
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);
154  continue;
155  }
156  (*locked_slot)(args...);
157  }
158  }
159 
160  template<typename ...U>
161  return_type invoke(not_void_return_type, U&&... args) const {
162  weak_slot_list weak_slots;
163  {
164  std::lock_guard<std::mutex> lck(slot_mutex_);
165  weak_slots = slot_list_->getWeakList();
166  }
167  return_type result;
168  for (const auto& weak_slot : weak_slots) {
169  auto locked_slot = weak_slot.first.lock();
170  if (locked_slot == nullptr)
171  continue;
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);
176  continue;
177  }
178  result = (*locked_slot)(args...);
179  }
180  return result;
181  }
182 
183  mutable std::shared_ptr<slot_list_type> slot_list_;
184  mutable std::mutex slot_mutex_;
185 };
186 
188 
189 
196 template<typename R, typename ...Args, typename Group>
197 class signal<R(Args...), Group> {
198  using impl = signal_impl<R(Args...), Group>;
199  public:
200  using slot_type = typename impl::slot_type;
201  using group_type = Group;
202  using return_type = typename impl::return_type;
203 
205  : pimpl_(std::make_shared<impl>()) {}
206 
208  return pimpl_->connect(slot, pos);
209  }
210 
212  return pimpl_->connect(group, slot, pos);
213  }
214 
215 // void disconnect(connection& conn) const {
216 // return pimpl_->disconnect(conn);
217 // }
218 //
219 // void disconnect(connection& conn) {
220 // return pimpl_->disconnect(conn);
221 // }
222 
223  void disconnect(group_type group) {
224  return pimpl_->disconnect(group);
225  }
226 
227  void disconnect(group_category group_cat) {
228  return pimpl_->disconnect(group_cat);
229  }
230 
231  void disconnect_all() {
232  return pimpl_->disconnect_all();
233  }
234 
235  auto size() const {
236  return pimpl_->size();
237  }
238 
239  template<typename ...U>
240  return_type operator()(U&&... args) {
241  return (*pimpl_)(std::forward<U>(args)...);
242  }
243 
244  template<typename ...U>
245  return_type operator()(U&&... args) const {
246  return (*pimpl_)(std::forward<U>(args)...);
247  }
248 
249  private:
250  std::shared_ptr<impl> pimpl_;
251 };
252 
254 
255 } // namespace vccc
256 
257 # endif // VCCC_SIGNAL_SIGNAL_H_
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
Definition: slot.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