35 #include <glibmm/threads.h>
37 #include <boost/bind/protect.hpp>
38 #include <boost/enable_shared_from_this.hpp>
45 #define DEBUG_PBD_SIGNAL_CONNECTIONS
48 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
53 using namespace std::placeholders;
69 , _debug_connection (false)
73 virtual void disconnect (std::shared_ptr<Connection>) = 0;
74 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
81 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
92 template <
typename Iter>
95 while (first != last) {
104 template <
typename Combiner,
typename _Signature>
107 template <
typename Combiner,
typename R,
typename... A>
122 static void compositor (
typename std::function<
void(A...)> f,
143 typename std::conditional_t<std::is_void_v<R>, R,
typename Combiner::result_type>
148 return _slots.empty ();
153 return _slots.size ();
161 void disconnect (std::shared_ptr<Connection> c);
165 template <
typename R>
168 template <
typename _Signature>
171 template <
typename R,
typename... A>
179 , _invalidation_record (ir)
181 if (_invalidation_record) {
182 _invalidation_record->ref ();
189 SignalBase* signal = _signal.exchange (0, std::memory_order_acq_rel);
204 if (_invalidation_record) {
205 _invalidation_record->unref ();
212 if (!_signal.exchange (0, std::memory_order_acq_rel)) {
222 if (_invalidation_record) {
223 _invalidation_record->unref ();
297 template <
typename Combiner,
typename R,
typename... A>
303 event_loop->
call_slot (ir, std::bind (f, a...));
306 template <
typename Combiner,
typename R,
typename... A>
309 _in_dtor.store (
true, std::memory_order_release);
312 for (
typename Slots::const_iterator i = _slots.begin(); i != _slots.end(); ++i) {
313 i->first->signal_going_away ();
324 template <
typename Combiner,
typename R,
typename... A>
329 c = _connect (0, slot);
339 template <
typename Combiner,
typename R,
typename... A>
372 template <
typename Combiner,
typename R,
typename... A>
383 clist.
add_connection (_connect (ir, [slot, event_loop, ir](A... a) {
384 return compositor(slot, event_loop, ir, a...);
393 template <
typename Combiner,
typename R,
typename... A>
404 c = _connect (ir, [slot, event_loop, ir](A... a) {
405 return compositor(slot, event_loop, ir, a...);
414 template <
typename Combiner,
typename R,
typename... A>
415 typename std::conditional_t<std::is_void_v<R>, R,
typename Combiner::result_type>
426 if constexpr (std::is_void_v<R>) {
427 for (
typename Slots::const_iterator i = s.begin(); i != s.end(); ++i) {
434 bool still_there =
false;
437 still_there = _slots.find (i->first) != _slots.end ();
446 for (
typename Slots::const_iterator i = s.begin(); i != s.end(); ++i) {
453 bool still_there =
false;
456 still_there = _slots.find (i->first) != _slots.end ();
460 r.push_back ((i->second)(a...));
466 return c (r.begin(), r.end());
470 template <
typename Combiner,
typename R,
typename... A>
471 std::shared_ptr<Connection>
475 std::shared_ptr<Connection> c (
new Connection (
this, ir));
478 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
479 if (_debug_connection) {
480 std::cerr <<
"+++++++ CONNECT " <<
this <<
" size now " << _slots.size() << std::endl;
487 template <
typename Combiner,
typename R,
typename... A>
493 while (!lm.locked()) {
494 if (_in_dtor.load (std::memory_order_acquire)) {
505 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
506 if (_debug_connection) {
507 std::cerr <<
"------- DISCCONNECT " <<
this <<
" size now " << _slots.size() << std::endl;
std::atomic< SignalBase * > _signal
Glib::Threads::Mutex _mutex
PBD::EventLoop::InvalidationRecord * _invalidation_record
Connection(SignalBase *b, PBD::EventLoop::InvalidationRecord *ir)
virtual bool call_slot(InvalidationRecord *, const std::function< void()> &)=0
std::optional< R > result_type
Glib::Threads::Mutex _scoped_connection_lock
void add_connection(const UnscopedConnection &c)
ConnectionList _scoped_connection_list
std::list< ScopedConnection * > ConnectionList
virtual ~ScopedConnectionList()
ScopedConnectionList(const ScopedConnectionList &)=delete
ScopedConnection(UnscopedConnection c)
UnscopedConnection const & the_connection() const
std::atomic< bool > _in_dtor
virtual void disconnect(std::shared_ptr< Connection >)=0
void set_debug_connection(bool yn)
Glib::Threads::Mutex _mutex
std::map< std::shared_ptr< Connection >, slot_function_type > Slots
std::function< R(A...)> slot_function_type
std::shared_ptr< Connection > UnscopedConnection
void stacktrace(std::ostream &out, int levels=0, size_t start_level=0)
#define DEBUG_PBD_SIGNAL_CONNECTIONS
PBD::EventLoop * event_loop