mc_rtc  2.14.0
SignalSlot.h
Go to the documentation of this file.
1 /*
2  * Copyright 2015-2021 CNRS-UM LIRMM, CNRS-AIST JRL
3  */
4 
5 #pragma once
6 
7 #include <cassert>
8 #include <functional>
9 #include <vector>
10 
11 namespace mc_rtc
12 {
13 
14 template<typename... ArgsT>
15 struct Signal;
16 
17 template<typename... ArgsT>
18 struct Slot;
19 
36 template<typename... ArgsT>
37 struct Signal
38 {
39  using SignalT = Signal<ArgsT...>;
40  using SlotT = Slot<ArgsT...>;
41  friend SlotT;
42  using CallbackT = std::function<void(ArgsT...)>;
43 
44  Signal() = default;
45 
50  template<typename Callable>
51  SlotT connect(Callable && callback)
52  {
53  SlotT out{this, next_slot_};
54  if(next_slot_ < callbacks_.size()) { callbacks_[next_slot_] = callback; }
55  else
56  {
57  callbacks_.push_back(callback);
58  }
59  next_slot_++;
60  while(next_slot_ < callbacks_.size() && callbacks_[next_slot_]) { next_slot_++; }
61  return out;
62  }
63 
69  void signal(ArgsT... args)
70  {
71  for(auto & c : callbacks_)
72  {
73  if(c) { c(args...); }
74  }
75  }
76 
81  struct Proxy
82  {
83  Proxy(SignalT & self) : self_(self) {}
84 
85  template<typename Callable>
86  SlotT connect(Callable && callback)
87  {
88  return self_.connect(std::forward<Callable>(callback));
89  }
90 
91  private:
92  SignalT & self_;
93  };
94 
95 protected:
96  void disconnect(size_t idx)
97  {
98  assert(idx < callbacks_.size());
99  callbacks_[idx] = {};
100  next_slot_ = std::min(idx, next_slot_);
101  }
102  std::vector<CallbackT> callbacks_;
103  size_t next_slot_ = 0;
104 };
105 
111 template<typename... ArgsT>
112 struct Slot
113 {
114  using SignalT = Signal<ArgsT...>;
115  friend SignalT;
116 
117  Slot() = default;
118  Slot(const Slot &) = delete;
119  Slot(Slot && rhs)
120  {
121  signal_ = rhs.signal_;
122  idx_ = rhs.idx_;
123  rhs.signal_ = nullptr;
124  }
125  Slot & operator=(const Slot &) = delete;
126  Slot & operator=(Slot && rhs)
127  {
128  if(&rhs == this) { return *this; }
129  signal_ = rhs.signal_;
130  idx_ = rhs.idx_;
131  rhs.signal_ = nullptr;
132  return *this;
133  }
134 
135  ~Slot() { disconnect(); }
136 
137  void disconnect()
138  {
139  if(signal_)
140  {
141  signal_->disconnect(idx_);
142  signal_ = nullptr;
143  }
144  }
145 
146 protected:
147  Slot(SignalT * sig, size_t idx) : signal_(sig), idx_(idx) {}
148 
149 private:
150  SignalT * signal_ = nullptr;
151  size_t idx_ = 0;
152 };
153 
154 } // namespace mc_rtc
Definition: Contact.h:88
Definition: SignalSlot.h:82
SlotT connect(Callable &&callback)
Definition: SignalSlot.h:86
Proxy(SignalT &self)
Definition: SignalSlot.h:83
Definition: SignalSlot.h:38
void signal(ArgsT... args)
Definition: SignalSlot.h:69
void disconnect(size_t idx)
Definition: SignalSlot.h:96
friend SlotT
Definition: SignalSlot.h:41
size_t next_slot_
Definition: SignalSlot.h:103
SlotT connect(Callable &&callback)
Definition: SignalSlot.h:51
std::function< void(ArgsT...)> CallbackT
Definition: SignalSlot.h:42
std::vector< CallbackT > callbacks_
Definition: SignalSlot.h:102
Signal()=default
Definition: SignalSlot.h:113
Slot(SignalT *sig, size_t idx)
Definition: SignalSlot.h:147
Slot & operator=(Slot &&rhs)
Definition: SignalSlot.h:126
~Slot()
Definition: SignalSlot.h:135
Signal< ArgsT... > SignalT
Definition: SignalSlot.h:114
Slot(const Slot &)=delete
Slot & operator=(const Slot &)=delete
void disconnect()
Definition: SignalSlot.h:137
Slot()=default
Slot(Slot &&rhs)
Definition: SignalSlot.h:119
friend SignalT
Definition: SignalSlot.h:115