2 Copyright (C) 2009 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__
24 #include <glibmm/thread.h>
25 #include <boost/signals2.hpp>
26 #include <boost/noncopyable.hpp>
30 typedef boost::signals2::connection UnscopedConnection;
31 typedef boost::signals2::connection Connection;
32 typedef boost::signals2::scoped_connection ScopedConnection;
34 class ScopedConnectionList : public boost::noncopyable
37 ScopedConnectionList();
38 ~ScopedConnectionList ();
40 void add_connection (const UnscopedConnection& c);
41 void drop_connections ();
43 template<typename S> void scoped_connect (S& sig, const typename S::slot_function_type& sf) {
44 add_connection (sig.connect (sf));
48 /* this class is not copyable */
49 ScopedConnectionList(const ScopedConnectionList&);
51 /* this lock is shared by all instances of a ScopedConnectionList.
52 We do not want one mutex per list, and since we only need the lock
53 when adding or dropping connections, which are generally occuring
54 in object creation and UI operations, the contention on this
55 lock is low and not of significant consequence. Even though
56 boost::signals2 is thread-safe, this additional list of
57 scoped connections needs to be protected in 2 cases:
59 (1) (unlikely) we make a connection involving a callback on the
60 same object from 2 threads. (wouldn't that just be appalling
63 (2) where we are dropping connections in one thread and adding
67 static Glib::StaticMutex _lock;
69 typedef std::list<ScopedConnection*> ConnectionList;
77 typedef boost::signals2::signal<R()> SignalType;
79 void connect (ScopedConnectionList& clist,
80 const typename SignalType::slot_function_type& slot) {
81 clist.add_connection (_signal.connect (slot));
84 void connect (Connection& c,
85 const typename SignalType::slot_function_type& slot) {
86 c = _signal.connect (slot);
89 typename SignalType::result_type operator()() {
97 template<typename R, typename A>
101 typedef boost::signals2::signal<R(A)> SignalType;
103 void connect (ScopedConnectionList& clist,
104 const typename SignalType::slot_function_type& slot) {
105 clist.add_connection (_signal.connect (slot));
108 void connect (Connection& c,
109 const typename SignalType::slot_function_type& slot) {
110 c = _signal.connect (slot);
113 typename SignalType::result_type operator()(A arg1) {
114 return _signal (arg1);
121 template<typename R, typename A1, typename A2>
125 typedef boost::signals2::signal<R(A1, A2)> SignalType;
127 void connect (ScopedConnectionList& clist,
128 const typename SignalType::slot_function_type& slot) {
129 clist.add_connection (_signal.connect (slot));
132 void connect (Connection& c,
133 const typename SignalType::slot_function_type& slot) {
134 c = _signal.connect (slot);
137 typename SignalType::result_type operator()(A1 arg1, A2 arg2) {
138 return _signal (arg1, arg2);
145 template<typename R, typename A1, typename A2, typename A3>
149 typedef boost::signals2::signal<R(A1,A2,A3)> SignalType;
151 void connect (ScopedConnectionList& clist,
152 const typename SignalType::slot_function_type& slot) {
153 clist.add_connection (_signal.connect (slot));
156 void connect (Connection& c,
157 const typename SignalType::slot_function_type& slot) {
158 c = _signal.connect (slot);
161 typename SignalType::result_type operator()(A1 arg1, A2 arg2, A3 arg3) {
162 return _signal (arg1, arg2, arg3);
171 #endif /* __pbd_signals_h__ */