Prefer the usage of SingleShotConnection

Currently we're doing something manually, which, since Qt6 is a
dedicated feature. Use that instead for less error-prone disconnections
for our single-shot signals.

Lets not re-invent the wheel for something that has been (potentially
faster rather then slower) invented for this exact usecase.

We will promote the usage of Qt::SingleShotConnection, so as good
teachers we should be using it as well.

Pick-to: 6.8
Change-Id: I3b2b9f176f06d91b4d0946a38c53a4c2614c8a01
Reviewed-by:  Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
Dennis Oberst 2024-08-08 11:26:41 +02:00
parent c29f3291b6
commit 19fca04537
5 changed files with 67 additions and 81 deletions

View File

@ -63,25 +63,22 @@ void SimpleChatEngine::login(const QString &name, const QString &password)
// ![1]
auto stream = m_client->messageList(qtgrpc::examples::chat::None());
auto streamPtr = stream.get();
auto finishedConnection = std::make_shared<QMetaObject::Connection>();
*finishedConnection = QObject::connect(streamPtr, &QGrpcServerStream::finished, this,
[this, finishedConnection,
stream = std::move(stream)](const QGrpcStatus &status) {
if (!status.isOk()) {
qCritical() << "Stream error(" << status.code()
<< "):" << status.message();
}
if (status.code()
== QtGrpc::StatusCode::Unauthenticated) {
emit authFailed();
} else if (status.code() != QtGrpc::StatusCode::Ok) {
emit networkError(status.message());
setState(Disconnected);
} else {
setState(Disconnected);
}
disconnect(*finishedConnection);
});
QObject::connect(
streamPtr, &QGrpcServerStream::finished, this,
[this, stream = std::move(stream)](const QGrpcStatus &status) {
if (!status.isOk()) {
qCritical() << "Stream error(" << status.code() << "):" << status.message();
}
if (status.code() == QtGrpc::StatusCode::Unauthenticated) {
emit authFailed();
} else if (status.code() != QtGrpc::StatusCode::Ok) {
emit networkError(status.message());
setState(Disconnected);
} else {
setState(Disconnected);
}
},
Qt::SingleShotConnection);
QObject::connect(streamPtr, &QGrpcServerStream::messageReceived, this,
[this, name, password, stream = streamPtr]() {

View File

@ -144,13 +144,13 @@ void QGrpcClientBasePrivate::addStream(QGrpcOperation *grpcStream)
activeStreams.remove(grpcStream);
});
auto finishedConnection = std::make_shared<QMetaObject::Connection>();
*finishedConnection = QObject::connect(grpcStream, &QGrpcOperation::finished, q,
[this, grpcStream, finishedConnection] {
Q_ASSERT(activeStreams.contains(grpcStream));
activeStreams.remove(grpcStream);
QObject::disconnect(*finishedConnection);
});
QObject::connect(
grpcStream, &QGrpcOperation::finished, q,
[this, grpcStream] {
Q_ASSERT(activeStreams.contains(grpcStream));
activeStreams.remove(grpcStream);
},
Qt::SingleShotConnection);
const auto it = activeStreams.insert(grpcStream);
Q_ASSERT(it.second);
}

View File

@ -360,18 +360,17 @@ void Http2Handler::attachStream(QHttp2Stream *stream_)
});
Q_ASSERT(parentChannel != nullptr);
auto errorConnection = std::make_shared<QMetaObject::Connection>();
*errorConnection = QObject::connect(
QObject::connect(
m_stream.get(), &QHttp2Stream::errorOccurred, parentChannel,
[parentChannel, errorConnection, this](quint32 http2ErrorCode, const QString &errorString) {
[parentChannel, this](quint32 http2ErrorCode, const QString &errorString) {
if (!m_operation.expired()) {
auto channelOp = m_operation.lock();
emit channelOp->finished(QGrpcStatus{ http2ErrorToStatusCode(http2ErrorCode),
errorString });
}
parentChannel->deleteHandler(this);
QObject::disconnect(*errorConnection);
});
},
Qt::SingleShotConnection);
QObject::connect(m_stream.get(), &QHttp2Stream::dataReceived, channelOpPtr,
[channelOpPtr, parentChannel, this](const QByteArray &data, bool endStream) {

View File

@ -38,22 +38,18 @@ void connectMultipleReceiveOperationFinished(QJSEngine *jsEngine,
auto *operationPtr = operation.get();
QtGrpcQuickFunctional::validateEngineAndOperation(jsEngine, operationPtr);
auto finishConnection = std::make_shared<QMetaObject::Connection>();
*finishConnection = QObject::connect(operationPtr, &QGrpcOperation::finished, jsEngine,
[successCallback, errorCallback, jsEngine,
finishConnection,
operation = std::move(operation)](const QGrpcStatus
&status) {
// We take 'operation' by copy so that its lifetime
// is extended until this lambda is destroyed.
if (QtGrpcQuickFunctional::
checkReceivedStatus(jsEngine, status,
errorCallback)
&& successCallback.isCallable()) {
successCallback.call();
}
QObject::disconnect(*finishConnection);
});
QObject::connect(
operationPtr, &QGrpcOperation::finished, jsEngine,
[successCallback, errorCallback, jsEngine,
operation = std::move(operation)](const QGrpcStatus &status) {
// We take 'operation' by copy so that its lifetime
// is extended until this lambda is destroyed.
if (QtGrpcQuickFunctional::checkReceivedStatus(jsEngine, status, errorCallback)
&& successCallback.isCallable()) {
successCallback.call();
}
},
Qt::SingleShotConnection);
}
void handleReceivedMessageImpl(QJSEngine *jsEngine, std::optional<QJSValue> message,
@ -77,19 +73,16 @@ void Private::connectSingleReceiveOperationFinishedImpl(QJSEngine *jsEngine,
auto *operationPtr = operation.get();
QtGrpcQuickFunctional::validateEngineAndOperation(jsEngine, operationPtr);
auto finishConnection = std::make_shared<QMetaObject::Connection>();
*finishConnection = QObject::
connect(operationPtr, &QGrpcCallReply::finished, jsEngine,
[jsEngine, successCallback, errorCallback, finishConnection, impl,
operation = std::move(operation)](const QGrpcStatus &status) {
// We take 'operation' by copy so that its lifetime
// is extended until this lambda is destroyed.
if (QtGrpcQuickFunctional::checkReceivedStatus(jsEngine, status,
errorCallback))
impl(jsEngine, operation.get(), successCallback, errorCallback);
QObject::disconnect(*finishConnection);
});
QObject::connect(
operationPtr, &QGrpcCallReply::finished, jsEngine,
[jsEngine, successCallback, errorCallback, impl,
operation = std::move(operation)](const QGrpcStatus &status) {
// We take 'operation' by copy so that its lifetime
// is extended until this lambda is destroyed.
if (QtGrpcQuickFunctional::checkReceivedStatus(jsEngine, status, errorCallback))
impl(jsEngine, operation.get(), successCallback, errorCallback);
},
Qt::SingleShotConnection);
}
void Private::makeServerStreamConnectionsImpl(QJSEngine *jsEngine,

View File

@ -66,27 +66,24 @@ void QtGrpcClientBenchmark::unaryCallHelper(qt::bench::UnaryCallRequest &request
auto reply = mClient.UnaryCall(request);
auto *replyPtr = reply.get();
auto connection = std::make_shared<QMetaObject::Connection>();
*connection = QObject::connect(replyPtr, &QGrpcCallReply::finished, &mClient,
[connection, reply = std::move(reply), this, &request,
&writes](const QGrpcStatus &status) {
if (writes == 0)
mTimer.start();
if (status.isOk()) {
if (++writes < mCalls) {
unaryCallHelper(request, writes);
} else {
Client::printRpcResult("UnaryCall",
mTimer.nsecsElapsed(),
writes);
mLoop.quit();
}
} else {
qDebug() << "FAILED: " << status;
mLoop.quit();
}
QObject::disconnect(*connection);
});
QObject::connect(
replyPtr, &QGrpcCallReply::finished, &mClient,
[reply = std::move(reply), this, &request, &writes](const QGrpcStatus &status) {
if (writes == 0)
mTimer.start();
if (status.isOk()) {
if (++writes < mCalls) {
unaryCallHelper(request, writes);
} else {
Client::printRpcResult("UnaryCall", mTimer.nsecsElapsed(), writes);
mLoop.quit();
}
} else {
qDebug() << "FAILED: " << status;
mLoop.quit();
}
},
Qt::SingleShotConnection);
}
void QtGrpcClientBenchmark::serverStreaming()