2 Copyright (C) 2009-2012 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef __pbd_signals_h__
21 #define __pbd_signals_h__
32 #include <glibmm/threads.h>
34 #include <boost/noncopyable.hpp>
35 #include <boost/bind.hpp>
36 #include <boost/bind/protect.hpp>
37 #include <boost/function.hpp>
38 #include <boost/enable_shared_from_this.hpp>
39 #include <boost/optional.hpp>
41 #include "pbd/libpbd_visibility.h"
42 #include "pbd/event_loop.h"
45 #define DEBUG_PBD_SIGNAL_CONNECTIONS
48 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
49 #include "pbd/stacktrace.h"
55 class LIBPBD_API Connection;
57 class LIBPBD_API SignalBase
61 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
62 : _debug_connection (false)
65 virtual ~SignalBase () {}
66 virtual void disconnect (boost::shared_ptr<Connection>) = 0;
67 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
68 void set_debug_connection (bool yn) { _debug_connection = yn; }
72 mutable Glib::Threads::Mutex _mutex;
73 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
74 bool _debug_connection;
78 class LIBPBD_API Connection : public boost::enable_shared_from_this<Connection>
81 Connection (SignalBase* b, PBD::EventLoop::InvalidationRecord* ir) : _signal (b), _invalidation_record (ir)
83 if (_invalidation_record) {
84 _invalidation_record->ref ();
90 Glib::Threads::Mutex::Lock lm (_mutex);
92 _signal->disconnect (shared_from_this ());
99 if (_invalidation_record) {
100 _invalidation_record->unref ();
104 void signal_going_away ()
106 Glib::Threads::Mutex::Lock lm (_mutex);
107 if (_invalidation_record) {
108 _invalidation_record->unref ();
114 Glib::Threads::Mutex _mutex;
116 PBD::EventLoop::InvalidationRecord* _invalidation_record;
120 class /*LIBPBD_API*/ OptionalLastValue
123 typedef boost::optional<R> result_type;
125 template <typename Iter>
126 result_type operator() (Iter first, Iter last) const {
128 while (first != last) {
137 typedef boost::shared_ptr<Connection> UnscopedConnection;
139 class LIBPBD_API ScopedConnection
142 ScopedConnection () {}
143 ScopedConnection (UnscopedConnection c) : _c (c) {}
144 ~ScopedConnection () {
155 ScopedConnection& operator= (UnscopedConnection const & o)
167 UnscopedConnection _c;
170 class LIBPBD_API ScopedConnectionList : public boost::noncopyable
173 ScopedConnectionList();
174 virtual ~ScopedConnectionList ();
176 void add_connection (const UnscopedConnection& c);
177 void drop_connections ();
180 /* this class is not copyable */
181 ScopedConnectionList(const ScopedConnectionList&);
183 /* Even though our signals code is thread-safe, this additional list of
184 scoped connections needs to be protected in 2 cases:
186 (1) (unlikely) we make a connection involving a callback on the
187 same object from 2 threads. (wouldn't that just be appalling
190 (2) where we are dropping connections in one thread and adding
194 Glib::Threads::Mutex _scoped_connection_lock;
196 typedef std::list<ScopedConnection*> ConnectionList;
197 ConnectionList _scoped_connection_list;
200 #include "pbd/signals_generated.h"
204 #endif /* __pbd_signals_h__ */