2 * Copyright 2003, The libsigc++ Development Team
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #ifndef _SIGC_SLOT_BASE_HPP_
20 #define _SIGC_SLOT_BASE_HPP_
22 #include <sigc++config.h>
23 #include <sigc++/trackable.h>
24 #include <sigc++/functors/functor_trait.h>
31 typedef void* (*hook)(void*);
33 /** Internal representation of a slot.
34 * Derivations of this class can be considered as a link
35 * between a slot and the functor that the slot should
36 * execute in operator(). This link is needed because in
37 * libsigc++ the slot doesn't necessarily have exactly the
38 * same function signature as the functor, thus allowing for
39 * implicit conversions.
41 * The base class slot_rep serves the purpose to
42 * - form a common pointer type (slot_rep*),
43 * - offer the possibility to create duplicates (dup()),
44 * - offer a notification callback (notify()),
45 * - implement some of slot_base's interface that depends
46 * on the notification callback, i.e.
47 * -# the possibility to set a single parent with a callback
48 * (set_parent()) that is executed from notify(),
49 * -# a generic function pointer, call_, that is simply
50 * set to zero in notify() to invalidate the slot.
52 * slot_rep inherits trackable so that connection objects can
53 * refer to the slot and are notified when the slot is destroyed.
55 struct SIGC_API slot_rep : public trackable
57 slot_rep(const slot_rep& src) = delete;
58 slot_rep& operator=(const slot_rep& src) = delete;
60 slot_rep(slot_rep&& src) = delete;
61 slot_rep& operator=(slot_rep&& src) = delete;
63 /* NB: Instead of slot_rep we could inherit slot_base from trackable.
64 * However, a simple benchmark seems to indicate that this slows
65 * down dereferencing of slot list iterators. Martin. */
67 /// Callback that invokes the contained functor.
68 /* This can't be a virtual function since number of arguments
69 * must be flexible. We use function pointers to slot_call::call_it()
70 * instead. call_ is set to zero to indicate that the slot is invalid.
74 /// Callback that detaches the slot_rep object from referred trackables and destroys it.
75 /* This could be a replaced by a virtual dtor. However since this struct is
76 * crucual for the efficiency of the whole library we want to avoid this.
80 /** Callback that makes a deep copy of the slot_rep object.
81 * @return A deep copy of the slot_rep object.
85 /** Callback of parent_. */
88 /** Parent object whose callback cleanup_ is executed on notification. */
91 inline slot_rep(hook call__, hook destroy__, hook dup__) noexcept
92 : call_(call__), destroy_(destroy__), dup_(dup__), cleanup_(nullptr), parent_(nullptr) {}
97 // only MSVC needs this to guarantee that all new/delete are executed from the DLL module
98 #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY
99 void* operator new(size_t size_);
100 void operator delete(void* p);
103 /** Destroys the slot_rep object (but doesn't delete it).
105 inline void destroy()
106 { if (destroy_) (*destroy_)(this); }
108 /** Makes a deep copy of the slot_rep object.
109 * @return A deep copy of the slot_rep object.
111 inline slot_rep* dup() const
112 { return reinterpret_cast<slot_rep*>((*dup_)(const_cast<slot_rep*>(this))); }
114 /** Set the parent with a callback.
115 * slots have one parent exclusively.
116 * @param parent The new parent.
117 * @param cleanup The callback to execute from notify().
119 inline void set_parent(void* parent, hook cleanup) noexcept
125 /// Invalidates the slot and executes the parent's cleanup callback.
128 /** Callback that invalidates the slot.
129 * This callback is registered in every object of a trackable
130 * inherited type that is referred by this slot_rep object.
131 * It is executed when the slot becomes invalid because of some
132 * referred object dying.
133 * @param data The slot_rep object that is becoming invalid (@p this).
135 static void* notify(void* data);
138 /** Functor used to add a dependency to a trackable.
139 * Consequently slot_rep::notify() gets executed when the
140 * trackable is destroyed or overwritten.
142 struct SIGC_API slot_do_bind
144 /** The slot_rep object trackables should notify on destruction. */
147 /** Construct a slot_do_bind functor.
148 * @param rep The slot_rep object trackables should notify on destruction.
150 inline slot_do_bind(slot_rep* rep) noexcept : rep_(rep) {}
152 /** Adds a dependency to @p t.
153 * @param t The trackable object to add a callback to.
155 inline void operator()(const trackable* t) const
156 { t->add_destroy_notify_callback(rep_, &slot_rep::notify); }
159 /// Functor used to remove a dependency from a trackable.
160 struct SIGC_API slot_do_unbind
162 /** The slot_rep object trackables don't need to notify on destruction any more. */
165 /** Construct a slot_do_unbind functor.
166 * @param rep The slot_rep object trackables don't need to notify on destruction any more.
168 inline slot_do_unbind(slot_rep* rep) noexcept : rep_(rep) {}
170 /** Removes a dependency from @p t.
171 * @param t The trackable object to remove the callback from.
173 inline void operator()(const trackable* t) const
174 { t->remove_destroy_notify_callback(rep_); }
177 } //namespace internal
180 /** @defgroup slot Slots
181 * Slots are type-safe representations of callback methods and functions.
182 * A slot can be constructed from any function object or function, regardless of
183 * whether it is a global function, a member method, static, or virtual.
185 * @section slots-creating Creating Slots
187 * Use the sigc::mem_fun() or sigc::ptr_fun() template functions to get a sigc::slot, like so:
189 * sigc::slot<void, int> sl = sigc::mem_fun(someobj, &SomeClass::somemethod);
193 * sigc::slot<void, int> sl = sigc::ptr_fun(&somefunction);
197 * m_Button.signal_clicked().connect( sigc::mem_fun(*this, &MyWindow::on_button_clicked) );
200 * The compiler will complain if SomeClass::somemethod, etc. have the wrong signature.
202 * You can also pass slots as method parameters where you might normally pass a function pointer.
204 * @section slots-auto-disconnect Member Methods and Automatic Disconnection
206 * See @ref mem_fun "sigc::mem_fun()" about deriving from sigc::trackable to prevent member
207 * methods from being called after the instance has been destroyed.
209 * @section slots-auto auto
211 * sigc::mem_fun() and sigc::ptr_fun() return functors, but those functors are
214 * sigc::slot<void, int> sl = sigc::mem_fun(someobj, &SomeClass::somemethod);
216 * is not equivalent to
218 * auto sl = sigc::mem_fun(someobj, &SomeClass::somemethod); // Not a slot!
221 * If you don't explicitly use a sigc::slot then the slot could call a method
222 * on an instance after it has been destroyed even if the method is in a class
223 * that derives from sigc::trackable.
225 * @section slots-with-lambdas C++ Lambdas
227 * A C++11 lambda expression is a functor (function object). It is automatically
228 * wrapped in a slot, if it is connected to a signal.
230 * auto on_response = [&someobj] (int response_id)
232 * someobj.somemethod(response_id);
233 * somefunction(response_id);
235 * m_Dialog.signal_response().connect(on_response);
238 * If you connect a C++11 lambda expression or a std::function<> instance to
239 * a signal or assign it to a slot,
240 * - With libsigc++ versions before 2.6, if the return type is not void,
241 you must use the #SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE macro,
242 * - if your functor contains references to sigc::trackable derived objects,
243 * those objects will not be tracked, unless you also use sigc::track_obj().
245 * @ingroup sigcfunctors
248 /** Base type for slots.
249 * slot_base integrates most of the interface of the derived
250 * sigc::slot templates. slots
251 * can be connected to signals, be disconnected at some later point
252 * (disconnect()) and temporarily be blocked (block(), unblock()).
253 * The validity of a slot can be tested with empty().
255 * The internal representation of a sigc::internal::slot_rep derived
256 * type is built from slot_base's derivations. set_parent() is used to
257 * register a notification callback that is executed when the slot gets
258 * invalid. add_destroy_notify_callback() is used by connection objects
259 * to add a notification callback that is executed on destruction.
263 class SIGC_API slot_base : public functor_base
265 typedef internal::slot_rep rep_type;
267 // Move operations are not declared noexcept because
268 // 1. they may copy instead of move
269 // 2. when they don't copy, they call src.rep_->notify_callbacks(), which
270 // may throw an exception.
272 /// Constructs an empty slot.
273 slot_base() noexcept;
275 /** Constructs a slot from an existing slot_rep object.
276 * @param rep The slot_rep object this slot should contain.
278 explicit slot_base(rep_type* rep) noexcept;
280 /** Constructs a slot, copying an existing one.
281 * @param src The existing slot to copy.
283 slot_base(const slot_base& src);
285 /** Constructs a slot, moving an existing one.
286 * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
287 * @param src The existing slot to move or copy.
289 slot_base(slot_base&& src);
293 /** Tests whether a slot is null, because the default constructor was used.
294 * Test a slot for null like so:
300 explicit operator bool() const noexcept;
302 /** Sets the parent of this slot.
303 * This function is used by signals to register a notification callback.
304 * This notification callback is executed when the slot becomes invalid
305 * because of some referred object dying.
306 * @param parent The new parent.
307 * @param cleanup The notification callback.
309 void set_parent(void* parent, void* (*cleanup)(void*)) const noexcept;
311 typedef trackable::func_destroy_notify func_destroy_notify;
312 /** Add a callback that is executed (notified) when the slot is detroyed.
313 * This function is used internally by connection objects.
314 * @param data Passed into func upon notification.
315 * @param func Callback executed upon destruction of the object.
317 void add_destroy_notify_callback(void* data, func_destroy_notify func) const;
319 /** Remove a callback previously installed with add_destroy_notify_callback().
320 * The callback is not executed.
321 * @param data Parameter passed into previous call to add_destroy_notify_callback().
323 void remove_destroy_notify_callback(void* data) const;
325 /** Returns whether the slot is invalid.
326 * @return @p true if the slot is invalid (empty).
328 inline bool empty() const noexcept
329 { return (!rep_ || !rep_->call_); }
331 /** Returns whether the slot is blocked.
332 * @return @p true if the slot is blocked.
334 inline bool blocked() const noexcept
337 /** Sets the blocking state.
338 * If @e should_block is @p true then the blocking state is set.
339 * Subsequent calls to slot::operator()() don't invoke the functor
340 * contained by this slot until unblock() or block() with
341 * @e should_block = @p false is called.
342 * @param should_block Indicates whether the blocking state should be set or unset.
343 * @return @p true if the slot was in blocking state before.
345 bool block(bool should_block = true) noexcept;
347 /** Unsets the blocking state.
348 * @return @p true if the slot was in blocking state before.
350 bool unblock() noexcept;
352 /** Disconnects the slot.
353 * Invalidates the slot and notifies the parent.
357 //The Tru64 and Solaris Forte 5.5 compilers needs this operator=() to be public. I'm not sure why, or why it needs to be protected usually. murrayc.
360 /** Overrides this slot, making a copy from another slot.
361 * @param src The slot from which to make a copy.
364 slot_base& operator=(const slot_base& src);
366 /** Overrides this slot, making a move from another slot.
367 * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
368 * @param src The slot from which to move or copy.
371 slot_base& operator=(slot_base&& src);
373 public: // public to avoid template friend declarations
374 /** Typed slot_rep object that contains a functor. */
375 mutable rep_type *rep_;
377 /** Indicates whether the slot is blocked. */
381 void delete_rep_with_check();
386 #endif //_SIGC_SLOT_BASE_HPP_