updated sconstruct for g3/g4/g5 safe building
[ardour.git] / libs / sigc++2 / sigc++ / signal_base.h
1 // -*- c++ -*-
2 /*
3  * Copyright 2002, The libsigc++ Development Team
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2.1 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20
21 #ifndef _SIGC_SIGNAL_BASE_H_
22 #define _SIGC_SIGNAL_BASE_H_
23
24 #include <list>
25 #include <sigc++config.h>
26 #include <sigc++/type_traits.h>
27 #include <sigc++/trackable.h>
28 #include <sigc++/functors/slot.h>
29 #include <sigc++/functors/mem_fun.h>
30
31 namespace sigc
32 {
33
34 namespace internal
35 {
36
37 /** Implementation of the signal interface.
38  * signal_impl manages a list of slots. When a slot becomes
39  * invalid (because some referred object dies), notify() is executed.
40  * notify() either calls sweep() directly or defers the execution of
41  * sweep() when the signal is being emitted. sweep() removes all
42  * invalid slot from the list.
43  */
44 struct SIGC_API signal_impl
45 {
46   typedef size_t size_type;
47   typedef std::list<slot_base>::iterator       iterator_type;
48   typedef std::list<slot_base>::const_iterator const_iterator_type;
49
50   signal_impl();
51
52   // only MSVC needs this to guarantee that all new/delete are executed from the DLL module
53 #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY
54   void* operator new(size_t size_);
55   void operator delete(void* p);
56 #endif
57
58   /// Increments the reference counter.
59   inline void reference()
60     { ++ref_count_; }
61
62   /// Increments the reference and execution counter.
63   inline void reference_exec()
64     { ++ref_count_; ++exec_count_; }
65
66   /** Decrements the reference counter.
67    * The object is deleted when the reference counter reaches zero.
68    */
69   inline void unreference()
70     { if (!(--ref_count_)) delete this; }
71
72   /** Decrements the reference and execution counter.
73    * Invokes sweep() if the execution counter reaches zero and the
74    * removal of one or more slots has been deferred.
75    */
76   inline void unreference_exec()
77     {
78       if (!(--ref_count_)) delete this;
79       else if (!(--exec_count_) && deferred_) sweep();
80     }
81
82   /** Returns whether the list of slots is empty.
83    * @return @p true if the list of slots is empty.
84    */
85   inline bool empty() const
86     { return slots_.empty(); }
87
88   /// Empties the list of slots.
89   void clear();
90
91   /** Returns the number of slots in the list.
92    * @return The number of slots in the list.
93    */
94   size_type size() const;
95
96   /** Adds a slot at the bottom of the list of slots.
97    * @param slot_ The slot to add to the list of slots.
98    * @return An iterator pointing to the new slot in the list.
99    */
100   iterator_type connect(const slot_base& slot_);
101
102   /** Adds a slot at the given position into the list of slots.
103    * @param i An iterator indicating the position where @p slot_ should be inserted.
104    * @param slot_ The slot to add to the list of slots.
105    * @return An iterator pointing to the new slot in the list.
106    */
107   iterator_type insert(iterator_type i, const slot_base& slot_);
108
109   /** Removes the slot at the given position from the list of slots.
110    * @param i An iterator pointing to the slot to be removed.
111    * @return An iterator pointing to the slot in the list after the one removed.
112    */
113   iterator_type erase(iterator_type i);
114
115   /// Removes invalid slots from the list of slots.
116   void sweep();
117
118   /** Callback that is executed when some slot becomes invalid.
119    * This callback is registered in every slot when inserted into
120    * the list of slots. It is executed when a slot becomes invalid
121    * because of some referred object being destroyed.
122    * It either calls sweep() directly or defers the execution of
123    * sweep() when the signal is being emitted.
124    * @param d The signal object (@p this).
125    */
126   static void* notify(void* d);
127
128   /** Reference counter.
129    * The object is destroyed when @em ref_count_ reaches zero.
130    */
131   short ref_count_;
132
133   /** Execution counter.
134    * Indicates whether the signal is being emitted.
135    */
136   short exec_count_;
137
138   /// Indicates whether the execution of sweep() is being deferred.
139   bool deferred_;
140
141   /// The list of slots.
142   std::list<slot_base> slots_;
143 };
144
145 /// Exception safe sweeper for cleaning up invalid slots on the slot list.
146 struct SIGC_API signal_exec
147 {
148   /// The parent sigc::signal_impl object.
149   signal_impl* sig_;
150
151   /** Increments the reference and execution counter of the parent sigc::signal_impl object.
152    * @param sig The parent sigc::signal_impl object.
153    */
154   inline signal_exec(const signal_impl* sig)
155     : sig_(const_cast<signal_impl*>(sig) )
156     { sig_->reference_exec(); }
157
158   /// Decrements the reference and execution counter of the parent sigc::signal_impl object.
159   inline ~signal_exec()
160     { sig_->unreference_exec(); }
161 };
162
163 } /* namespace internal */
164
165
166 /** @defgroup signal Signals
167  * Use sigc::signal::connect() with sigc::mem_fun() and sigc::ptr_fun() to connect a method or function with a signal.
168  *
169  * @code
170  * signal_clicked.connect( sigc::mem_fun(*this, &MyWindow::on_clicked) );
171  * @endcode
172  *
173  * When the signal is emitted your method will be called.
174  *
175  * signal::connect() returns a connection, which you can later use to disconnect your method.
176  * If the type of your object inherits from sigc::trackable the method is disconnected
177  * automatically when your object is destroyed.
178  *
179  * When signals are copied they share the underlying information,
180  * so you can have a protected/private sigc::signal member and a public accessor method.
181  *
182  * signal and slot objects provide the core functionality of this
183  * library. A slot is a container for an arbitrary functor.
184  * A signal is a list of slots that are executed on emission.
185  * For compile time type safety a list of template arguments
186  * must be provided for the signal template that determines the
187  * parameter list for emission. Functors and closures are converted
188  * into slots implicitely on connection, triggering compiler errors
189  * if the given functor or closure cannot be invoked with the
190  * parameter list of the signal to connect to.
191  */
192
193 /** Base class for the sigc::signal# templates.
194  * signal_base integrates most of the interface of the derived sigc::signal#
195  * templates. The implementation, however, resides in sigc::internal::signal_impl.
196  * A sigc::internal::signal_impl object is dynamically allocated from signal_base
197  * when first connecting a slot to the signal. This ensures that empty signals
198  * don't waste memory.
199  *
200  * @ingroup signal
201  */
202 struct SIGC_API signal_base : public trackable
203 {
204   typedef size_t size_type;
205
206   signal_base();
207
208   signal_base(const signal_base& src);
209
210   ~signal_base();
211
212   signal_base& operator = (const signal_base& src);
213
214   /** Returns whether the list of slots is empty.
215    * @return @p true if the list of slots is empty.
216    */
217   inline bool empty() const
218     { return (!impl_ || impl_->empty()); }
219
220   /// Empties the list of slots.
221   void clear();
222
223   /** Returns the number of slots in the list.
224    * @return The number of slots in the list.
225    */
226   size_type size() const;
227
228 protected:
229   typedef internal::signal_impl::iterator_type iterator_type;
230
231   /** Adds a slot at the bottom of the list of slots.
232    * @param slot_ The slot to add to the list of slots.
233    * @return An iterator pointing to the new slot in the list.
234    */
235   iterator_type connect(const slot_base& slot_);
236
237   /** Adds a slot at the given position into the list of slots.
238    * @param i An iterator indicating the position where @e slot_ should be inserted.
239    * @param slot_ The slot to add to the list of slots.
240    * @return An iterator pointing to the new slot in the list.
241    */
242   iterator_type insert(iterator_type i, const slot_base& slot_);
243
244   /** Removes the slot at the given position from the list of slots.
245    * @param i An iterator pointing to the slot to be removed.
246    * @return An iterator pointing to the slot in the list after the one removed.
247    */
248   iterator_type erase(iterator_type i);
249
250   /** Returns the signal_impl object encapsulating the list of slots.
251    * @return The signal_impl object encapsulating the list of slots.
252    */
253   internal::signal_impl* impl() const;
254
255   /// The signal_impl object encapsulating the slot list.
256   mutable internal::signal_impl* impl_;
257 };
258
259 } //namespace sigc
260
261 #endif /* _SIGC_SIGNAL_BASE_H_ */