ardour
signals.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009-2012 Paul Davis
3 
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.
8 
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.
13 
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.
17 
18 */
19 
20 #ifndef __pbd_signals_h__
21 #define __pbd_signals_h__
22 
23 #include <list>
24 #include <map>
25 
26 #ifdef nil
27 #undef nil
28 #endif
29 
30 #include <glibmm/threads.h>
31 
32 #include <boost/noncopyable.hpp>
33 #include <boost/bind.hpp>
34 #include <boost/bind/protect.hpp>
35 #include <boost/function.hpp>
36 #include <boost/enable_shared_from_this.hpp>
37 #include <boost/optional.hpp>
38 
39 #include "pbd/libpbd_visibility.h"
40 #include "pbd/event_loop.h"
41 
42 #ifndef NDEBUG
43 #define DEBUG_PBD_SIGNAL_CONNECTIONS
44 #endif
45 
46 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
47 #include "pbd/stacktrace.h"
48 #include <iostream>
49 #endif
50 
51 namespace PBD {
52 
54 
56 {
57 public:
59 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
60  : _debug_connection (false)
61 #endif
62  {}
63  virtual ~SignalBase () {}
64  virtual void disconnect (boost::shared_ptr<Connection>) = 0;
65 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
66  void set_debug_connection (bool yn) { _debug_connection = yn; }
67 #endif
68 
69 protected:
70  Glib::Threads::Mutex _mutex;
71 #ifdef DEBUG_PBD_SIGNAL_CONNECTIONS
73 #endif
74 };
75 
77 {
78 public:
79  Connection (SignalBase* b) : _signal (b) {}
80 
81  void disconnect ()
82  {
83  Glib::Threads::Mutex::Lock lm (_mutex);
84  if (_signal) {
85  _signal->disconnect (shared_from_this ());
86  _signal = 0;
87  }
88  }
89 
91  {
92  Glib::Threads::Mutex::Lock lm (_mutex);
93  _signal = 0;
94  }
95 
96 private:
97  Glib::Threads::Mutex _mutex;
99 };
100 
101 template<typename R>
102 class /*LIBPBD_API*/ OptionalLastValue
103 {
104 public:
105  typedef boost::optional<R> result_type;
106 
107  template <typename Iter>
108  result_type operator() (Iter first, Iter last) const {
109  result_type r;
110  while (first != last) {
111  r = *first;
112  ++first;
113  }
114 
115  return r;
116  }
117 };
118 
120 
122 {
123 public:
125  ScopedConnection (UnscopedConnection c) : _c (c) {}
127  disconnect ();
128  }
129 
130  void disconnect ()
131  {
132  if (_c) {
133  _c->disconnect ();
134  }
135  }
136 
137  ScopedConnection& operator= (UnscopedConnection const & o)
138  {
139  if (_c == o) {
140  return *this;
141  }
142 
143  disconnect ();
144  _c = o;
145  return *this;
146  }
147 
148 private:
149  UnscopedConnection _c;
150 };
151 
152 class LIBPBD_API ScopedConnectionList : public boost::noncopyable
153 {
154  public:
156  virtual ~ScopedConnectionList ();
157 
158  void add_connection (const UnscopedConnection& c);
159  void drop_connections ();
160 
161  private:
162  /* this class is not copyable */
164 
165  /* Even though our signals code is thread-safe, this additional list of
166  scoped connections needs to be protected in 2 cases:
167 
168  (1) (unlikely) we make a connection involving a callback on the
169  same object from 2 threads. (wouldn't that just be appalling
170  programming style?)
171 
172  (2) where we are dropping connections in one thread and adding
173  one from another.
174  */
175 
176  Glib::Threads::Mutex _lock;
177 
178  typedef std::list<ScopedConnection*> ConnectionList;
179  ConnectionList _list;
180 };
181 
182 #include "pbd/signals_generated.h"
183 
184 } /* namespace */
185 
186 #endif /* __pbd_signals_h__ */
virtual ~SignalBase()
Definition: signals.h:63
Connection(SignalBase *b)
Definition: signals.h:79
ConnectionList _list
Definition: signals.h:179
#define LIBPBD_API
void disconnect()
Definition: signals.h:81
UnscopedConnection _c
Definition: signals.h:149
bool _debug_connection
Definition: signals.h:72
void signal_going_away()
Definition: signals.h:90
SignalBase * _signal
Definition: signals.h:98
ScopedConnection(UnscopedConnection c)
Definition: signals.h:125
Glib::Threads::Mutex _mutex
Definition: signals.h:70
Glib::Threads::Mutex _mutex
Definition: signals.h:97
std::list< ScopedConnection * > ConnectionList
Definition: signals.h:178
void set_debug_connection(bool yn)
Definition: signals.h:66
Glib::Threads::Mutex _lock
Definition: signals.h:176
boost::optional< R > result_type
Definition: signals.h:105
boost::shared_ptr< Connection > UnscopedConnection
Definition: signals.h:119
Definition: debug.h:30
result_type operator()(Iter first, Iter last) const
Definition: signals.h:108