summaryrefslogtreecommitdiff
path: root/sigc++/functors/slot_base.cc
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjell.ahlstedt@bredband.net>2015-10-21 18:43:56 +0200
committerKjell Ahlstedt <kjell.ahlstedt@bredband.net>2015-10-21 18:43:56 +0200
commitcabc88f6c2e25432a8e6245c5af114ebb0de04b8 (patch)
tree95f1e0ca97aa8ec2724523599dfe1f83bba04f77 /sigc++/functors/slot_base.cc
parent02339149a28e26151402076e8cf1abd00f7dd92b (diff)
downloadsigc++-cabc88f6c2e25432a8e6245c5af114ebb0de04b8.tar.gz
slot and signal: Fix move constructors and move assignments
* sigc++/functors/macros/slot.h.m4: Add documentation. * sigc++/functors/slot_base.[h|cc]: Fix the move operators of slot_base. Don't move a connected slot. * sigc++/signal_base.cc: Fix the move assignment of signal_base. * tests/test_signal_move.cc: * tests/test_slot_move.cc: Really test move assignment. Bug #756484.
Diffstat (limited to 'sigc++/functors/slot_base.cc')
-rw-r--r--sigc++/functors/slot_base.cc72
1 files changed, 60 insertions, 12 deletions
diff --git a/sigc++/functors/slot_base.cc b/sigc++/functors/slot_base.cc
index c15c213..7500d84 100644
--- a/sigc++/functors/slot_base.cc
+++ b/sigc++/functors/slot_base.cc
@@ -125,12 +125,35 @@ slot_base::slot_base(const slot_base& src)
}
slot_base::slot_base(slot_base&& src) noexcept
-: rep_(std::move(src.rep_)),
- blocked_(std::move(src.blocked_))
+: rep_(nullptr),
+ blocked_(src.blocked_)
{
- //Wipe src:
- src.rep_ = nullptr;
- src.blocked_ = false;
+ if (src.rep_)
+ {
+ if (src.rep_->parent_)
+ {
+ // src is connected to a parent, e.g. a sigc::signal.
+ // Copy, don't move! See https://bugzilla.gnome.org/show_bug.cgi?id=756484
+
+ //Check call_ so we can ignore invalidated slots.
+ //Otherwise, destroyed bound reference parameters (whose destruction
+ //caused the slot's invalidation) may be used during dup().
+ if (src.rep_->call_)
+ rep_ = src.rep_->dup();
+ else
+ blocked_ = false; //Return the default invalid slot.
+ }
+ else
+ {
+ // src is not connected. Really move src.rep_.
+ src.rep_->notify_callbacks();
+ rep_ = src.rep_;
+
+ //Wipe src:
+ src.rep_ = nullptr;
+ src.blocked_ = false;
+ }
+ }
}
slot_base::~slot_base()
@@ -199,17 +222,42 @@ slot_base& slot_base::operator=(const slot_base& src)
slot_base& slot_base::operator=(slot_base&& src) noexcept
{
if (src.rep_ == rep_)
+ {
+ blocked_ = src.blocked_;
return *this;
-
- delete_rep_with_check();
+ }
- rep_ = std::move(src.rep_);
- blocked_ = std::move(src.blocked_);
+ if (src.empty())
+ {
+ delete_rep_with_check();
+ return *this;
+ }
- //Wipe src:
- src.rep_ = nullptr;
- src.blocked_ = false;
+ blocked_ = src.blocked_;
+ internal::slot_rep* new_rep_ = nullptr;
+ if (src.rep_->parent_)
+ {
+ // src is connected to a parent, e.g. a sigc::signal.
+ // Copy, don't move! See https://bugzilla.gnome.org/show_bug.cgi?id=756484
+ new_rep_ = src.rep_->dup();
+ }
+ else
+ {
+ // src is not connected. Really move src.rep_.
+ src.rep_->notify_callbacks();
+ new_rep_ = src.rep_;
+ //Wipe src:
+ src.rep_ = nullptr;
+ src.blocked_ = false;
+ }
+
+ if (rep_) // Silently exchange the slot_rep.
+ {
+ new_rep_->set_parent(rep_->parent_, rep_->cleanup_);
+ delete rep_; // Calls destroy(), but does not call disconnect().
+ }
+ rep_ = new_rep_;
return *this;
}