diff options
author | Murray Cumming <murrayc@murrayc.com> | 2016-03-03 10:53:11 +0100 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2016-03-03 11:42:39 +0100 |
commit | 6de9eacd24a5b9e03b900dda16f94d2b1c858f4b (patch) | |
tree | 506e68681d50322a49f7cee0ce8f790c40880010 | |
parent | e438a231c25dfab4525a9ed37369771f1f54f1fd (diff) | |
download | sigc++-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.cc | 3 | ||||
-rw-r--r-- | sigc++/connection.h | 4 | ||||
-rw-r--r-- | sigc++/functors/slot.h | 3 | ||||
-rw-r--r-- | sigc++/functors/slot_base.cc | 14 | ||||
-rw-r--r-- | sigc++/functors/slot_base.h | 23 | ||||
-rw-r--r-- | sigc++/signal_base.cc | 6 | ||||
-rw-r--r-- | sigc++/signal_base.h | 4 | ||||
-rw-r--r-- | sigc++/trackable.cc | 8 | ||||
-rw-r--r-- | sigc++/trackable.h | 25 |
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, ¬ify); } -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(); |