NOOP, remove trailing tabs/whitespace.
[ardour.git] / libs / pbd / pbd / signals.h
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
53 class LIBPBD_API Connection;
54
55 class LIBPBD_API SignalBase
56 {
57 public:
58         SignalBase ()
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
72         bool _debug_connection;
73 #endif
74 };
75
76 class LIBPBD_API Connection : public boost::enable_shared_from_this<Connection>
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
90         void signal_going_away ()
91         {
92                 Glib::Threads::Mutex::Lock lm (_mutex);
93                 _signal = 0;
94         }
95
96 private:
97         Glib::Threads::Mutex _mutex;
98         SignalBase* _signal;
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
119 typedef boost::shared_ptr<Connection> UnscopedConnection;
120
121 class LIBPBD_API ScopedConnection
122 {
123 public:
124         ScopedConnection () {}
125         ScopedConnection (UnscopedConnection c) : _c (c) {}
126         ~ScopedConnection () {
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:
155         ScopedConnectionList();
156         virtual ~ScopedConnectionList ();
157
158         void add_connection (const UnscopedConnection& c);
159         void drop_connections ();
160
161   private:
162         /* this class is not copyable */
163         ScopedConnectionList(const ScopedConnectionList&);
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__ */