summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMurray Cumming <murrayc@murrayc.com>2016-03-03 10:53:11 +0100
committerMurray Cumming <murrayc@murrayc.com>2016-03-03 11:42:39 +0100
commit6de9eacd24a5b9e03b900dda16f94d2b1c858f4b (patch)
tree506e68681d50322a49f7cee0ce8f790c40880010
parente438a231c25dfab4525a9ed37369771f1f54f1fd (diff)
downloadsigc++-6de9eacd24a5b9e03b900dda16f94d2b1c858f4b.tar.gz
Add and use notifiable base class instead of void*.
Use notifiable as the base class for trackable, connection, signal_impl, self_and_iter and destroy_notify_struct. Use this notifiable* instead of void* for the destroy/notify callback data. This is a little more type-safe and self-documenting. Bug #302152
-rw-r--r--sigc++/connection.cc3
-rw-r--r--sigc++/connection.h4
-rw-r--r--sigc++/functors/slot.h3
-rw-r--r--sigc++/functors/slot_base.cc14
-rw-r--r--sigc++/functors/slot_base.h23
-rw-r--r--sigc++/signal_base.cc6
-rw-r--r--sigc++/signal_base.h4
-rw-r--r--sigc++/trackable.cc8
-rw-r--r--sigc++/trackable.h25
9 files changed, 49 insertions, 41 deletions
diff --git a/sigc++/connection.cc b/sigc++/connection.cc
index 0d1d52e..79d1202 100644
--- a/sigc++/connection.cc
+++ b/sigc++/connection.cc
@@ -99,11 +99,10 @@ void connection::set_slot(slot_base* sl)
slot_->add_destroy_notify_callback(this, &notify);
}
-void* connection::notify(void* data)
+void connection::notify(notifiable* data)
{
auto self = reinterpret_cast<connection*>(data);
self->slot_ = nullptr;
- return nullptr;
}
} /* namespace sigc */
diff --git a/sigc++/connection.h b/sigc++/connection.h
index 2405876..199b4e8 100644
--- a/sigc++/connection.h
+++ b/sigc++/connection.h
@@ -37,7 +37,7 @@ namespace sigc {
*
* @ingroup signal
*/
-struct SIGC_API connection
+struct SIGC_API connection : public notifiable
{
/** Constructs an empty connection object. */
connection() noexcept;
@@ -113,7 +113,7 @@ struct SIGC_API connection
/** Callback that is executed when the referred slot is destroyed.
* @param data The connection object notified (@p this).
*/
- static void* notify(void* data);
+ static void notify(notifiable* data);
private:
void set_slot(slot_base* sl);
diff --git a/sigc++/functors/slot.h b/sigc++/functors/slot.h
index 7a3713f..ea793c7 100644
--- a/sigc++/functors/slot.h
+++ b/sigc++/functors/slot.h
@@ -56,7 +56,7 @@ struct typed_slot_rep : public slot_rep
/** Detaches the stored functor from the other referred trackables and destroys it.
* This does not destroy the base slot_rep object.
*/
- static void* destroy(void* data)
+ static void destroy(notifiable* data)
{
self* self_ = static_cast<self*>(reinterpret_cast<slot_rep*>(data));
self_->call_ = nullptr;
@@ -67,7 +67,6 @@ struct typed_slot_rep : public slot_rep
* a) from the parent itself (in which case disconnect() leads to a segfault) or
* b) from a parentless slot (in which case disconnect() does nothing)
*/
- return nullptr;
}
/** Makes a deep copy of the slot_rep object.
diff --git a/sigc++/functors/slot_base.cc b/sigc++/functors/slot_base.cc
index 1b8285a..a0c4f7d 100644
--- a/sigc++/functors/slot_base.cc
+++ b/sigc++/functors/slot_base.cc
@@ -23,15 +23,14 @@ namespace
{
// Used by slot_rep::notify() and slot_base::operator=(). They must be
// notified, if the slot_rep is deleted when they call disconnect().
-struct destroy_notify_struct
+struct destroy_notify_struct : public sigc::notifiable
{
destroy_notify_struct() noexcept : deleted_(false) { }
- static void* notify(void* data) noexcept
+ static void notify(notifiable* data) noexcept
{
auto self_ = reinterpret_cast<destroy_notify_struct*>(data);
self_->deleted_ = true;
- return nullptr;
}
bool deleted_;
@@ -74,7 +73,7 @@ void slot_rep::disconnect()
}
//static
-void* slot_rep::notify(void* data)
+void slot_rep::notify(notifiable* data)
{
auto self_ = reinterpret_cast<slot_rep*>(data);
@@ -91,7 +90,6 @@ void* slot_rep::notify(void* data)
self_->destroy(); // Detach the stored functor from the other referred trackables and destroy it.
// destroy() might lead to deletion of self_. Bug #564005.
}
- return nullptr;
}
} // namespace internal
@@ -261,19 +259,19 @@ slot_base& slot_base::operator=(slot_base&& src)
return *this;
}
-void slot_base::set_parent(void* parent, void* (*cleanup)(void*)) const noexcept
+void slot_base::set_parent(notifiable* parent, notifiable::func_destroy_notify cleanup) const noexcept
{
if (rep_)
rep_->set_parent(parent, cleanup);
}
-void slot_base::add_destroy_notify_callback(void* data, func_destroy_notify func) const
+void slot_base::add_destroy_notify_callback(notifiable* data, func_destroy_notify func) const
{
if (rep_)
rep_->add_destroy_notify_callback(data, func);
}
-void slot_base::remove_destroy_notify_callback(void* data) const
+void slot_base::remove_destroy_notify_callback(notifiable* data) const
{
if (rep_)
rep_->remove_destroy_notify_callback(data);
diff --git a/sigc++/functors/slot_base.h b/sigc++/functors/slot_base.h
index 8ecd086..cd46cf3 100644
--- a/sigc++/functors/slot_base.h
+++ b/sigc++/functors/slot_base.h
@@ -75,7 +75,7 @@ struct SIGC_API slot_rep : public trackable
/* This could be a replaced by a virtual dtor. However since this struct is
* crucual for the efficiency of the whole library we want to avoid this.
*/
- hook destroy_;
+ func_destroy_notify destroy_;
/** Callback that makes a deep copy of the slot_rep object.
* @return A deep copy of the slot_rep object.
@@ -83,12 +83,12 @@ struct SIGC_API slot_rep : public trackable
hook dup_;
/** Callback of parent_. */
- hook cleanup_;
+ func_destroy_notify cleanup_;
/** Parent object whose callback cleanup_ is executed on notification. */
- void* parent_;
+ notifiable* parent_;
- inline slot_rep(hook call__, hook destroy__, hook dup__) noexcept
+ inline slot_rep(hook call__, notifiable::func_destroy_notify destroy__, hook dup__) noexcept
: call_(call__), destroy_(destroy__), dup_(dup__), cleanup_(nullptr), parent_(nullptr) {}
inline ~slot_rep()
@@ -116,7 +116,7 @@ struct SIGC_API slot_rep : public trackable
* @param parent The new parent.
* @param cleanup The callback to execute from notify().
*/
- inline void set_parent(void* parent, hook cleanup) noexcept
+ inline void set_parent(notifiable* parent, notifiable::func_destroy_notify cleanup) noexcept
{
parent_ = parent;
cleanup_ = cleanup;
@@ -132,7 +132,7 @@ struct SIGC_API slot_rep : public trackable
* referred object dying.
* @param data The slot_rep object that is becoming invalid (@p this).
*/
- static void* notify(void* data);
+ static void notify(notifiable* data);
};
/** Functor used to add a dependency to a trackable.
@@ -279,6 +279,8 @@ public:
*/
operator bool() const noexcept;
+ typedef notifiable::func_destroy_notify func_destroy_notify;
+
/** Sets the parent of this slot.
* This function is used by signals to register a notification callback.
* This notification callback is executed when the slot becomes invalid
@@ -286,21 +288,22 @@ public:
* @param parent The new parent.
* @param cleanup The notification callback.
*/
- void set_parent(void* parent, void* (*cleanup)(void*)) const noexcept;
+ void set_parent(notifiable* parent, notifiable::func_destroy_notify cleanup) const noexcept;
+
+
- typedef trackable::func_destroy_notify func_destroy_notify;
/** Add a callback that is executed (notified) when the slot is detroyed.
* This function is used internally by connection objects.
* @param data Passed into func upon notification.
* @param func Callback executed upon destruction of the object.
*/
- void add_destroy_notify_callback(void* data, func_destroy_notify func) const;
+ void add_destroy_notify_callback(notifiable* data, notifiable::func_destroy_notify func) const;
/** Remove a callback previously installed with add_destroy_notify_callback().
* The callback is not executed.
* @param data Parameter passed into previous call to add_destroy_notify_callback().
*/
- void remove_destroy_notify_callback(void* data) const;
+ void remove_destroy_notify_callback(notifiable* data) const;
/** Returns whether the slot is invalid.
* @return @p true if the slot is invalid (empty).
diff --git a/sigc++/signal_base.cc b/sigc++/signal_base.cc
index cc8342b..bbb1955 100644
--- a/sigc++/signal_base.cc
+++ b/sigc++/signal_base.cc
@@ -24,7 +24,7 @@ namespace internal {
// Data sent from signal_impl::insert() to slot_rep::set_parent() when a slot is
// connected, and then sent from slot_rep::disconnect() to signal_impl::notify()
// when the slot is disconnected. Bug 167714.
-struct self_and_iter
+struct self_and_iter : public notifiable
{
signal_impl* self_;
signal_impl::iterator_type iter_;
@@ -149,7 +149,7 @@ void signal_impl::sweep()
}
//static
-void* signal_impl::notify(void* d)
+void signal_impl::notify(notifiable* d)
{
std::unique_ptr<self_and_iter> si(static_cast<self_and_iter*>(d));
@@ -163,7 +163,7 @@ void* signal_impl::notify(void* d)
}
else // This is occuring during signal emission or slot erasure.
si->self_->deferred_ = true; // => sweep() will be called from ~signal_exec() after signal emission.
- return nullptr; // This is safer because we don't have to care about our
+ // This is safer because we don't have to care about our
// iterators in emit(), clear(), and erase().
}
diff --git a/sigc++/signal_base.h b/sigc++/signal_base.h
index f50a6cb..94037ca 100644
--- a/sigc++/signal_base.h
+++ b/sigc++/signal_base.h
@@ -42,7 +42,7 @@ namespace internal
* erase() to sweep() when the signal is being emitted. sweep() removes all
* invalid slots from the list.
*/
-struct SIGC_API signal_impl
+struct SIGC_API signal_impl : public notifiable
{
typedef std::size_t size_type;
typedef std::list<slot_base> slot_list;
@@ -167,7 +167,7 @@ struct SIGC_API signal_impl
* erase() to sweep() when the signal is being emitted.
* @param d A local structure, created in insert().
*/
- static void* notify(void* d);
+ static void notify(notifiable* d);
/** Reference counter.
* The object is destroyed when @em ref_count_ reaches zero.
diff --git a/sigc++/trackable.cc b/sigc++/trackable.cc
index 135d1ca..7c492ea 100644
--- a/sigc++/trackable.cc
+++ b/sigc++/trackable.cc
@@ -67,12 +67,12 @@ trackable::~trackable()
notify_callbacks();
}
-void trackable::add_destroy_notify_callback(void* data, func_destroy_notify func) const
+void trackable::add_destroy_notify_callback(notifiable* data, func_destroy_notify func) const
{
callback_list()->add_callback(data, func);
}
-void trackable::remove_destroy_notify_callback(void* data) const
+void trackable::remove_destroy_notify_callback(notifiable* data) const
{
callback_list()->remove_callback(data);
}
@@ -106,7 +106,7 @@ trackable_callback_list::~trackable_callback_list()
callback.func_(callback.data_);
}
-void trackable_callback_list::add_callback(void* data, func_destroy_notify func)
+void trackable_callback_list::add_callback(notifiable* data, func_destroy_notify func)
{
if (!clearing_) // TODO: Is it okay to silently ignore attempts to add dependencies when the list is being cleared?
// I'd consider this a serious application bug, since the app is likely to segfault.
@@ -127,7 +127,7 @@ void trackable_callback_list::clear()
clearing_ = false;
}
-void trackable_callback_list::remove_callback(void* data)
+void trackable_callback_list::remove_callback(notifiable* data)
{
for (callback_list::iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
{
diff --git a/sigc++/trackable.h b/sigc++/trackable.h
index 6f9b017..f148785 100644
--- a/sigc++/trackable.h
+++ b/sigc++/trackable.h
@@ -23,9 +23,12 @@
namespace sigc {
+struct notifiable;
+
namespace internal {
-typedef void* (*func_destroy_notify) (void* data);
+typedef void (*func_destroy_notify) (notifiable* data);
+
/** Destroy notification callback.
* A destroy notification callback consists of a data pointer and a
@@ -35,9 +38,9 @@ typedef void* (*func_destroy_notify) (void* data);
*/
struct SIGC_API trackable_callback
{
- void* data_;
+ notifiable* data_;
func_destroy_notify func_;
- trackable_callback(void* data, func_destroy_notify func) noexcept
+ trackable_callback(notifiable* data, func_destroy_notify func) noexcept
: data_(data), func_(func) {}
};
@@ -54,12 +57,12 @@ struct SIGC_API trackable_callback_list
* @param func The callback function.
*
*/
- void add_callback(void* data, func_destroy_notify func);
+ void add_callback(notifiable* data, func_destroy_notify func);
/** Remove the callback which has this data associated with it.
* @param data The data that was given as a parameter to add_callback().
*/
- void remove_callback(void* data);
+ void remove_callback(notifiable* data);
/** This invokes all of the callback functions.
*/
@@ -86,6 +89,12 @@ private:
} /* namespace internal */
+struct SIGC_API notifiable
+{
+ typedef internal::func_destroy_notify func_destroy_notify;
+};
+
+
/** Base class for objects with auto-disconnection.
* trackable must be inherited when objects shall automatically
* invalidate slots referring to them on destruction.
@@ -106,7 +115,7 @@ private:
*
* @ingroup signal
*/
-struct SIGC_API trackable
+struct SIGC_API trackable : public notifiable
{
// Concerning noexcept specifications:
// libsigc++ does not have complete control of what happens when notify_callbacks()
@@ -135,13 +144,13 @@ struct SIGC_API trackable
* @param data Passed into func upon notification.
* @param func Callback executed upon destruction of the object.
*/
- void add_destroy_notify_callback(void* data, func_destroy_notify func) const;
+ void add_destroy_notify_callback(notifiable* data, func_destroy_notify func) const;
/** Remove a callback previously installed with add_destroy_notify_callback().
* The callback is not executed.
* @param data Parameter passed into previous call to add_destroy_notify_callback().
*/
- void remove_destroy_notify_callback(void* data) const;
+ void remove_destroy_notify_callback(notifiable* data) const;
/// Execute and remove all previously installed callbacks.
void notify_callbacks();