diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2022-12-20 15:03:36 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-01-17 11:19:16 +0000 |
commit | c2556321d9ce585f1f71e3a8ffc88834df3e37b7 (patch) | |
tree | 56c1c0e31c8a67e293dd270ddfe92b87015ac543 | |
parent | db5f4117840af20e22fa785d8687e916956487ad (diff) | |
download | qtconnectivity-c2556321d9ce585f1f71e3a8ffc88834df3e37b7.tar.gz |
QWinRTLowEnergyServiceHandler: optimize behavior at disconnect
The QWinRTLowEnergyServiceHandler helper class is used to query low
energy service details. It works in a background thread and performs
multiple async operations to get the results.
As the class works in a background thread, we use
QWinRTFunctions::await() to wait for the results of async operations.
This allows to simplify the code.
In practice the user might want to disconnect from the device while
service details discovery is performed. Previously the background
thread was still performing all the requests.
This patch handles the already-existing
QLowEnergyControllerPrivateWinRT::abortConnection() signal and
provides the exit condition to all QWinRTFunctions::await() calls,
so that the background thread does not do unnecessary work.
Task-number: QTBUG-108461
Change-Id: I1db05c906beb0078de8a00fd5e32d589306f6665
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
(cherry picked from commit c68e5d0952036204b8d20b26f0de362b36c03511)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/bluetooth/qlowenergycontroller_winrt.cpp | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp index 307a401d..3822ed3a 100644 --- a/src/bluetooth/qlowenergycontroller_winrt.cpp +++ b/src/bluetooth/qlowenergycontroller_winrt.cpp @@ -131,6 +131,8 @@ public: public slots: void obtainCharList() { + auto exitCondition = [this]() { return mAbortRequested; }; + mIndicateChars.clear(); qCDebug(QT_BT_WINDOWS) << __FUNCTION__; ComPtr<IAsyncOperation<GattCharacteristicsResult *>> characteristicsOp; @@ -138,7 +140,8 @@ public slots: HRESULT hr = mDeviceService->GetCharacteristicsAsync(&characteristicsOp); EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr); hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(), - QWinRTFunctions::ProcessMainThreadEvents, 5000); + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr); GattCommunicationStatus status; hr = characteristicsResult->get_Status(&status); @@ -156,7 +159,7 @@ public slots: EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr); mCharacteristicsCountToBeDiscovered = characteristicsCount; - for (uint i = 0; i < characteristicsCount; ++i) { + for (uint i = 0; !mAbortRequested && (i < characteristicsCount); ++i) { ComPtr<IGattCharacteristic> characteristic; hr = characteristics->GetAt(i, &characteristic); if (FAILED(hr)) { @@ -182,7 +185,9 @@ public slots: DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain list of descriptors") ComPtr<IGattDescriptorsResult> descResult; - hr = QWinRTFunctions::await(descAsyncOp, descResult.GetAddressOf()); + hr = QWinRTFunctions::await(descAsyncOp, descResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor read result") quint16 handle; @@ -211,7 +216,9 @@ public slots: &readOp); DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not read characteristic") ComPtr<IGattReadResult> readResult; - hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf()); + hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic read result") if (!readResult) @@ -237,7 +244,7 @@ public slots: uint descriptorCount; hr = descriptors->get_Size(&descriptorCount); DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain list of descriptors' size") - for (uint j = 0; j < descriptorCount; ++j) { + for (uint j = 0; !mAbortRequested && (j < descriptorCount); ++j) { QLowEnergyServicePrivate::DescData descData; ComPtr<IGattDescriptor> descriptor; hr = descriptors->GetAt(j, &descriptor); @@ -257,7 +264,9 @@ public slots: &readOp); WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read descriptor value") ComPtr<IClientCharConfigDescriptorResult> readResult; - hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf()); + hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); WARN_AND_CONTINUE_IF_FAILED(hr, "Could not await descriptor read result") GattClientCharacteristicConfigurationDescriptorValue value; hr = readResult->get_ClientCharacteristicConfigurationDescriptor(&value); @@ -289,8 +298,10 @@ public slots: &readOp); WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read descriptor value") ComPtr<IGattReadResult> readResult; - hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf()); - WARN_AND_CONTINUE_IF_FAILED(hr, "Could await descriptor read result") + hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000, + exitCondition); + WARN_AND_CONTINUE_IF_FAILED(hr, "Could not await descriptor read result") if (descData.uuid == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) descData.value = byteArrayFromGattResult(readResult, true); else @@ -306,6 +317,11 @@ public slots: checkAllCharacteristicsDiscovered(); } + void setAbortRequested() + { + mAbortRequested = true; + } + private: bool checkAllCharacteristicsDiscovered(); void emitErrorAndQuitThread(HRESULT hr); @@ -320,6 +336,7 @@ public: quint16 mStartHandle = 0; quint16 mEndHandle = 0; QList<QBluetoothUuid> mIndicateChars; + bool mAbortRequested = false; signals: void charListObtained(const QBluetoothUuid &service, @@ -336,6 +353,8 @@ bool QWinRTLowEnergyServiceHandler::checkAllCharacteristicsDiscovered() mStartHandle, mEndHandle); QThread::currentThread()->quit(); return true; + } else if (mAbortRequested) { + QThread::currentThread()->quit(); } return false; @@ -1281,6 +1300,8 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetailsHelper( connect(thread, &QThread::started, worker, &QWinRTLowEnergyServiceHandler::obtainCharList); connect(thread, &QThread::finished, worker, &QObject::deleteLater); connect(worker, &QObject::destroyed, thread, &QObject::deleteLater); + connect(this, &QLowEnergyControllerPrivateWinRT::abortConnection, + worker, &QWinRTLowEnergyServiceHandler::setAbortRequested); connect(worker, &QWinRTLowEnergyServiceHandler::errorOccured, this, &QLowEnergyControllerPrivateWinRT::handleServiceHandlerError); connect(worker, &QWinRTLowEnergyServiceHandler::charListObtained, this, |