51 #include <ableton/build_system/Warnings.hpp>
53 #include <boost/signals2/signal.hpp>
69 template <
typename T1,
typename T2>
70 bool operator() (
const T1& a,
const T2& b)
84 struct down_signal_base
86 virtual ~down_signal_base();
87 virtual void send_down() = 0;
88 virtual void notify() = 0;
97 virtual ~up_signal_base() {}
98 virtual void send_up(
const T&) = 0;
99 virtual void send_up(T&&) = 0;
106 template <
typename T>
108 :
public std::enable_shared_from_this<down_signal<T> >
109 ,
public down_signal_base
112 using value_type = T;
114 down_signal(down_signal&&) =
default;
115 down_signal(
const down_signal&) =
delete;
116 down_signal& operator=(down_signal&&) =
default;
117 down_signal& operator=(
const down_signal&) =
delete;
120 : current_(
std::move(value))
122 , last_notified_(current_)
125 virtual void recompute() {}
126 virtual void recompute_deep() {}
128 const value_type& current()
const {
return current_; }
129 const value_type& last()
const {
return last_; }
131 void link(std::weak_ptr<down_signal_base> child)
134 using std::placeholders::_1;
135 assert(find_if(begin(children_), end(children_),
136 bind(owner_equals, child, _1))
138 "Child signal must not be linked twice");
139 children_.push_back(child);
142 template <
typename U>
143 void push_down(U&& value)
145 if (value != current_)
147 current_ = std::forward<U>(value);
148 needs_send_down_ =
true;
152 void send_down() final
155 if (needs_send_down_)
158 needs_send_down_ =
false;
159 needs_notify_ =
true;
161 for (
auto& wchild : children_)
163 if (
auto child = wchild.lock())
174 if (!needs_send_down_ && needs_notify_)
176 needs_notify_ =
false;
177 observers_(last_notified_, last_);
178 last_notified_ = last_;
180 auto garbage =
false;
181 for (std::size_t i = 0, size = children_.size(); i < size; ++i)
183 if (
auto child = children_[i].lock())
200 template <
typename Fn>
202 -> boost::signals2::connection
204 return observers_.connect(std::forward<Fn>(f));
208 -> boost::signals2::signal<void(
const value_type&,
222 mem_fn(&weak_ptr<down_signal_base>::expired)),
226 bool needs_send_down_ =
false;
227 bool needs_notify_ =
false;
230 value_type last_notified_;
231 std::vector<std::weak_ptr<down_signal_base> > children_;
232 boost::signals2::signal<void(
const value_type&,
233 const value_type&)> observers_;
239 template <
typename T>
241 :
public down_signal<T>
242 ,
public up_signal_base<T>
244 using down_signal<T>::down_signal;
C++ amazing templates and reusable implementations awesomeness.