Move-enable QSignalBlocker
When QSignalBlocker was reviewed, move semantics were asked for. This patch add them. This makes QSignalBlocker usable as a by-value argument (to transfer control of signal blocking into a function) as well as as a return value (to transfer control of signal blocking out of a function). Change-Id: I714aa2a283bb33dba76e860649e88ed202e913c5 Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
parent
5e519b31dc
commit
4031cb8610
@ -529,6 +529,27 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
|
||||
Calls \a{object}.blockSignals(true).
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
|
||||
|
||||
Move-constructs a signal blocker from \a other. \a other will have
|
||||
a no-op destructor, while repsonsibility for restoring the
|
||||
QObject::signalsBlocked() state is transferred to the new object.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other)
|
||||
|
||||
Move-assigns this signal blocker from \a other. \a other will have
|
||||
a no-op destructor, while repsonsibility for restoring the
|
||||
QObject::signalsBlocked() state is transferred to this object.
|
||||
|
||||
The object's signals this signal blocker was blocking prior to
|
||||
being moved to, if any, are unblocked \em except in the case where
|
||||
both instances block the same object's signals and \c *this is
|
||||
unblocked while \a other is not, at the time of the move.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QSignalBlocker::~QSignalBlocker()
|
||||
|
||||
|
@ -556,11 +556,16 @@ public:
|
||||
inline explicit QSignalBlocker(QObject &o);
|
||||
inline ~QSignalBlocker();
|
||||
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
inline QSignalBlocker(QSignalBlocker &&other);
|
||||
inline QSignalBlocker &operator=(QSignalBlocker &&other);
|
||||
#endif
|
||||
|
||||
inline void reblock();
|
||||
inline void unblock();
|
||||
private:
|
||||
Q_DISABLE_COPY(QSignalBlocker)
|
||||
QObject * const m_o;
|
||||
QObject * m_o;
|
||||
bool m_blocked;
|
||||
bool m_inhibited;
|
||||
};
|
||||
@ -577,6 +582,32 @@ QSignalBlocker::QSignalBlocker(QObject &o)
|
||||
m_inhibited(false)
|
||||
{}
|
||||
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
|
||||
: m_o(other.m_o),
|
||||
m_blocked(other.m_blocked),
|
||||
m_inhibited(other.m_inhibited)
|
||||
{
|
||||
other.m_o = 0;
|
||||
}
|
||||
|
||||
QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
// if both *this and other block the same object's signals:
|
||||
// unblock *this iff our dtor would unblock, but other's wouldn't
|
||||
if (m_o != other.m_o || (!m_inhibited && other.m_inhibited))
|
||||
unblock();
|
||||
m_o = other.m_o;
|
||||
m_blocked = other.m_blocked;
|
||||
m_inhibited = other.m_inhibited;
|
||||
// disable other:
|
||||
other.m_o = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
QSignalBlocker::~QSignalBlocker()
|
||||
{
|
||||
if (m_o && !m_inhibited)
|
||||
|
@ -103,6 +103,7 @@ private slots:
|
||||
void recursiveSignalEmission();
|
||||
#endif
|
||||
void signalBlocking();
|
||||
void signalBlockingMoveAssignment();
|
||||
void blockingQueuedConnection();
|
||||
void childEvents();
|
||||
void installEventFilter();
|
||||
@ -3030,6 +3031,105 @@ void tst_QObject::signalBlocking()
|
||||
receiver.reset();
|
||||
}
|
||||
|
||||
void tst_QObject::signalBlockingMoveAssignment()
|
||||
{
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
QObject o1, o2;
|
||||
|
||||
// move-assignment: both block other objects
|
||||
{
|
||||
QSignalBlocker b(&o1);
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
|
||||
QVERIFY(!o2.signalsBlocked());
|
||||
b = QSignalBlocker(&o2);
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
QVERIFY(o2.signalsBlocked());
|
||||
}
|
||||
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
QVERIFY(!o2.signalsBlocked());
|
||||
|
||||
// move-assignment: from inert other
|
||||
{
|
||||
QSignalBlocker b(&o1);
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
b = QSignalBlocker(0);
|
||||
}
|
||||
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
QVERIFY(!o2.signalsBlocked());
|
||||
|
||||
// move-assignment: to inert *this
|
||||
{
|
||||
QSignalBlocker b(0);
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
{
|
||||
QSignalBlocker inner(&o1);
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
b = std::move(inner);
|
||||
}
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
}
|
||||
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
QVERIFY(!o2.signalsBlocked());
|
||||
|
||||
// move-assignment: both block the same object, neither is unblocked
|
||||
{
|
||||
QSignalBlocker b(&o1);
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
{
|
||||
b.unblock(); // make sure inner.m_blocked = false
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
QSignalBlocker inner(&o1);
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
b.reblock();
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
b = std::move(inner);
|
||||
}
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
}
|
||||
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
QVERIFY(!o2.signalsBlocked());
|
||||
|
||||
// move-assignment: both block the same object, but *this is unblocked
|
||||
{
|
||||
QSignalBlocker b(&o1);
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
b.unblock();
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
b = QSignalBlocker(&o1);
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
}
|
||||
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
QVERIFY(!o2.signalsBlocked());
|
||||
|
||||
// move-assignment: both block the same object, but other is unblocked
|
||||
{
|
||||
QSignalBlocker b(&o1);
|
||||
{
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
QSignalBlocker inner(&o1);
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
inner.unblock();
|
||||
QVERIFY(o1.signalsBlocked());
|
||||
b = std::move(inner);
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
}
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
}
|
||||
|
||||
QVERIFY(!o1.signalsBlocked());
|
||||
QVERIFY(!o2.signalsBlocked());
|
||||
|
||||
#else
|
||||
QSKIP("This compiler is not in C++11 mode or doesn't support move semantics");
|
||||
#endif // Q_COMPILER_RVALUE_REFS
|
||||
}
|
||||
|
||||
void tst_QObject::blockingQueuedConnection()
|
||||
{
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user