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).
|
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()
|
\fn QSignalBlocker::~QSignalBlocker()
|
||||||
|
|
||||||
|
@ -556,11 +556,16 @@ public:
|
|||||||
inline explicit QSignalBlocker(QObject &o);
|
inline explicit QSignalBlocker(QObject &o);
|
||||||
inline ~QSignalBlocker();
|
inline ~QSignalBlocker();
|
||||||
|
|
||||||
|
#ifdef Q_COMPILER_RVALUE_REFS
|
||||||
|
inline QSignalBlocker(QSignalBlocker &&other);
|
||||||
|
inline QSignalBlocker &operator=(QSignalBlocker &&other);
|
||||||
|
#endif
|
||||||
|
|
||||||
inline void reblock();
|
inline void reblock();
|
||||||
inline void unblock();
|
inline void unblock();
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QSignalBlocker)
|
Q_DISABLE_COPY(QSignalBlocker)
|
||||||
QObject * const m_o;
|
QObject * m_o;
|
||||||
bool m_blocked;
|
bool m_blocked;
|
||||||
bool m_inhibited;
|
bool m_inhibited;
|
||||||
};
|
};
|
||||||
@ -577,6 +582,32 @@ QSignalBlocker::QSignalBlocker(QObject &o)
|
|||||||
m_inhibited(false)
|
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()
|
QSignalBlocker::~QSignalBlocker()
|
||||||
{
|
{
|
||||||
if (m_o && !m_inhibited)
|
if (m_o && !m_inhibited)
|
||||||
|
@ -103,6 +103,7 @@ private slots:
|
|||||||
void recursiveSignalEmission();
|
void recursiveSignalEmission();
|
||||||
#endif
|
#endif
|
||||||
void signalBlocking();
|
void signalBlocking();
|
||||||
|
void signalBlockingMoveAssignment();
|
||||||
void blockingQueuedConnection();
|
void blockingQueuedConnection();
|
||||||
void childEvents();
|
void childEvents();
|
||||||
void installEventFilter();
|
void installEventFilter();
|
||||||
@ -3030,6 +3031,105 @@ void tst_QObject::signalBlocking()
|
|||||||
receiver.reset();
|
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()
|
void tst_QObject::blockingQueuedConnection()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user