summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/CMakeLists.txt17
-rw-r--r--src/corelib/configure.cmake10
-rw-r--r--src/corelib/global/qcompilerdetection.h2
-rw-r--r--src/corelib/io/qiooperation_p.h20
-rw-r--r--src/corelib/io/qioring_p.h6
-rw-r--r--src/corelib/io/qioring_win.cpp104
-rw-r--r--src/corelib/io/qrandomaccessasyncfile.cpp25
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_darwin.mm79
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_p_p.h241
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_qioring.cpp61
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_threadpool.cpp79
-rw-r--r--src/corelib/tools/qeasingcurve.cpp10
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm25
13 files changed, 473 insertions, 206 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index ea8cf7b9c8e..539ad753ca6 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -590,17 +590,14 @@ if(QT_FEATURE_async_io)
DEFINES
QT_RANDOMACCESSASYNCFILE_QIORING
)
- elseif(QT_FEATURE_thread AND QT_FEATURE_future)
- # TODO: This should become the last (fallback) condition later.
- # We migth also want to rewrite it so that it does not depend on
- # QT_FEATURE_future.
- qt_internal_extend_target(Core
- SOURCES
- io/qrandomaccessasyncfile_threadpool.cpp
- DEFINES
- QT_RANDOMACCESSASYNCFILE_THREAD
- )
endif()
+ # This is the fallback condition that should be always available.
+ # TODO: try to rewrite it so that it does not depend on
+ # QT_FEATURE_future.
+ qt_internal_extend_target(Core
+ SOURCES
+ io/qrandomaccessasyncfile_threadpool.cpp
+ )
endif()
# This needs to be done before one below adds kernel32 because the symbols we use
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake
index 90a0e359c9f..7274b51cc0a 100644
--- a/src/corelib/configure.cmake
+++ b/src/corelib/configure.cmake
@@ -620,6 +620,10 @@ int main(void)
HRESULT hr = CreateIoRing(IORING_VERSION_3, flags, 1, 1, &ioRingHandle);
if (hr == IORING_E_SUBMISSION_QUEUE_FULL) // not valid, but test that this #define exists
return 0;
+ IORING_HANDLE_REF ref(HANDLE(nullptr));
+ IORING_BUFFER_REF bufRef(nullptr);
+ // The newest API addition that we require:
+ BuildIoRingWriteFile(ioRingHandle, ref, bufRef, -1, 0, FILE_WRITE_FLAGS_NONE, 0, IOSQE_FLAGS_NONE);
/* END TEST: */
return 0;
}
@@ -806,7 +810,7 @@ qt_feature("winsdkicu" PRIVATE
CONDITION TEST_winsdkicu
DISABLE QT_FEATURE_icu
)
-qt_feature("windows_ioring" PRIVATE
+qt_feature("windows-ioring" PRIVATE
LABEL "Windows I/O Ring"
AUTODETECT WIN32 AND CMAKE_HOST_SYSTEM_VERSION VERSION_GREATER_EQUAL 10.0.22000
CONDITION TEST_windows_ioring
@@ -1284,7 +1288,7 @@ qt_feature("openssl-hash" PRIVATE
qt_feature("async-io" PRIVATE
LABEL "Async File I/O"
PURPOSE "Provides support for asynchronous file I/O."
- CONDITION (QT_FEATURE_thread AND QT_FEATURE_future) OR APPLE OR (LINUX AND QT_FEATURE_liburing) OR (WIN32 AND QT_FEATURE_windows_ioring)
+ CONDITION QT_FEATURE_thread AND QT_FEATURE_future
)
qt_configure_add_summary_section(NAME "Qt Core")
@@ -1297,7 +1301,7 @@ qt_configure_add_summary_entry(ARGS "glib")
qt_configure_add_summary_entry(ARGS "icu")
qt_configure_add_summary_entry(ARGS "jemalloc")
qt_configure_add_summary_entry(ARGS "liburing")
-qt_configure_add_summary_entry(ARGS "windows_ioring")
+qt_configure_add_summary_entry(ARGS "windows-ioring")
qt_configure_add_summary_entry(ARGS "timezone_tzdb")
qt_configure_add_summary_entry(ARGS "system-libb2")
qt_configure_add_summary_entry(ARGS "mimetype-database")
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 0b42af7686c..b2d79cca603 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1404,7 +1404,7 @@ static_assert(!std::is_convertible_v<std::nullptr_t, bool>,
#if defined(__cplusplus)
#ifdef __cpp_constinit
-# if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+# if defined(Q_CC_MSVC) && _MSC_VER < 1940 && !defined(Q_CC_CLANG)
// https://developercommunity.visualstudio.com/t/C:-constinit-for-an-optional-fails-if-/1406069
# define Q_CONSTINIT
# else
diff --git a/src/corelib/io/qiooperation_p.h b/src/corelib/io/qiooperation_p.h
index 56845167ede..1486719a7e8 100644
--- a/src/corelib/io/qiooperation_p.h
+++ b/src/corelib/io/qiooperation_p.h
@@ -72,6 +72,9 @@ protected:
Q_DECLARE_PRIVATE(QIOOperation)
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOReadWriteOperationBase : public QIOOperation
@@ -86,6 +89,11 @@ protected:
QIOReadWriteOperationBase() = delete;
Q_DISABLE_COPY_MOVE(QIOReadWriteOperationBase)
explicit QIOReadWriteOperationBase(QIOOperationPrivate &dd, QObject *parent = nullptr);
+
+ friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOReadOperation : public QIOReadWriteOperationBase
@@ -101,6 +109,9 @@ protected:
explicit QIOReadOperation(QIOOperationPrivate &dd, QObject *parent = nullptr);
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOWriteOperation : public QIOReadWriteOperationBase
@@ -116,6 +127,9 @@ protected:
explicit QIOWriteOperation(QIOOperationPrivate &dd, QObject *parent = nullptr);
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOVectoredReadOperation : public QIOReadWriteOperationBase
@@ -131,6 +145,9 @@ protected:
explicit QIOVectoredReadOperation(QIOOperationPrivate &dd, QObject *parent = nullptr);
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOVectoredWriteOperation : public QIOReadWriteOperationBase
@@ -146,6 +163,9 @@ protected:
explicit QIOVectoredWriteOperation(QIOOperationPrivate &dd, QObject *parent = nullptr);
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qioring_p.h b/src/corelib/io/qioring_p.h
index 0db832bc6bf..8fdaf48f8f6 100644
--- a/src/corelib/io/qioring_p.h
+++ b/src/corelib/io/qioring_p.h
@@ -91,6 +91,10 @@ enum class Operation : quint8 {
// clang-format on
Q_ENUM_NS(Operation);
#undef DEFINE_ENTRY
+
+#ifdef Q_OS_WIN
+struct IORingApiTable;
+#endif
}; // namespace QtPrivate
template <QtPrivate::Operation Op>
@@ -221,9 +225,11 @@ private:
std::optional<QWinEventNotifier> notifier;
HIORING ioRingHandle = nullptr;
HANDLE eventHandle = INVALID_HANDLE_VALUE;
+ const QtPrivate::IORingApiTable *apiTable;
bool initialized = false;
bool queueWasFull = false;
+
[[nodiscard]]
RequestPrepResult prepareRequest(GenericRequestType &request);
QIORing::ReadWriteStatus handleReadCompletion(
diff --git a/src/corelib/io/qioring_win.cpp b/src/corelib/io/qioring_win.cpp
index 42c51f428d6..b2f188486d0 100644
--- a/src/corelib/io/qioring_win.cpp
+++ b/src/corelib/io/qioring_win.cpp
@@ -24,6 +24,59 @@ static_assert(sizeof(qsizetype) > sizeof(UINT32),
using namespace Qt::StringLiterals;
+namespace QtPrivate {
+#define FOREACH_WIN_IORING_FUNCTION(Fn) \
+ Fn(BuildIoRingReadFile) \
+ Fn(BuildIoRingWriteFile) \
+ Fn(BuildIoRingFlushFile) \
+ Fn(BuildIoRingCancelRequest) \
+ Fn(QueryIoRingCapabilities) \
+ Fn(CreateIoRing) \
+ Fn(GetIoRingInfo) \
+ Fn(SubmitIoRing) \
+ Fn(CloseIoRing) \
+ Fn(PopIoRingCompletion) \
+ Fn(SetIoRingCompletionEvent) \
+ /**/
+struct IORingApiTable
+{
+#define DefineIORingFunction(Name) \
+ using Name##Fn = decltype(&::Name); \
+ Name##Fn Name = nullptr;
+
+ FOREACH_WIN_IORING_FUNCTION(DefineIORingFunction)
+
+#undef DefineIORingFunction
+};
+
+static const IORingApiTable *getApiTable()
+{
+ static const IORingApiTable apiTable = []() {
+ IORingApiTable apiTable;
+ const HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
+ if (Q_UNLIKELY(!kernel32)) // how would this happen
+ return apiTable;
+
+#define ResolveFunction(Name) \
+ apiTable.Name = IORingApiTable::Name##Fn(QFunctionPointer(GetProcAddress(kernel32, #Name)));
+
+ FOREACH_WIN_IORING_FUNCTION(ResolveFunction)
+
+#undef ResolveFunction
+ return apiTable;
+ }();
+
+#define TEST_TABLE_OK(X) \
+ apiTable.X && /* chain */
+#define BOOL_CHAIN(...) (__VA_ARGS__ true)
+ const bool success = BOOL_CHAIN(FOREACH_WIN_IORING_FUNCTION(TEST_TABLE_OK));
+#undef BOOL_CHAIN
+#undef TEST_TABLE_OK
+
+ return success ? std::addressof(apiTable) : nullptr;
+}
+} // namespace QtPrivate
+
static HRESULT buildReadOperation(HIORING ioRingHandle, qintptr fd, QSpan<std::byte> destination,
quint64 offset, quintptr userData)
{
@@ -32,8 +85,10 @@ static HRESULT buildReadOperation(HIORING ioRingHandle, qintptr fd, QSpan<std::b
const IORING_BUFFER_REF bufferRef(destination.data());
const auto maxSize = q26::saturate_cast<UINT32>(destination.size());
Q_ASSERT(maxSize == destination.size());
- return BuildIoRingReadFile(ioRingHandle, fileRef, bufferRef, maxSize, offset, userData,
- IOSQE_FLAGS_NONE);
+ const auto *apiTable = QtPrivate::getApiTable();
+ Q_ASSERT(apiTable); // If we got this far it needs to be here
+ return apiTable->BuildIoRingReadFile(ioRingHandle, fileRef, bufferRef, maxSize, offset,
+ userData, IOSQE_FLAGS_NONE);
}
static HRESULT buildWriteOperation(HIORING ioRingHandle, qintptr fd, QSpan<const std::byte> source,
@@ -44,16 +99,18 @@ static HRESULT buildWriteOperation(HIORING ioRingHandle, qintptr fd, QSpan<const
const IORING_BUFFER_REF bufferRef(const_cast<std::byte *>(source.data()));
const auto maxSize = q26::saturate_cast<UINT32>(source.size());
Q_ASSERT(maxSize == source.size());
+ const auto *apiTable = QtPrivate::getApiTable();
+ Q_ASSERT(apiTable); // If we got this far it needs to be here
// @todo: FILE_WRITE_FLAGS can be set to write-through, could be used for Unbuffered mode.
- return BuildIoRingWriteFile(ioRingHandle, fileRef, bufferRef, maxSize, offset,
- FILE_WRITE_FLAGS_NONE, userData, IOSQE_FLAGS_NONE);
+ return apiTable->BuildIoRingWriteFile(ioRingHandle, fileRef, bufferRef, maxSize, offset,
+ FILE_WRITE_FLAGS_NONE, userData, IOSQE_FLAGS_NONE);
}
QIORing::~QIORing()
{
if (initialized) {
CloseHandle(eventHandle);
- CloseIoRing(ioRingHandle);
+ apiTable->CloseIoRing(ioRingHandle);
}
}
@@ -62,8 +119,13 @@ bool QIORing::initializeIORing()
if (initialized)
return true;
+ if (apiTable = QtPrivate::getApiTable(); !apiTable) {
+ qCWarning(lcQIORing, "Failed to retrieve API table");
+ return false;
+ }
+
IORING_CAPABILITIES capabilities;
- QueryIoRingCapabilities(&capabilities);
+ apiTable->QueryIoRingCapabilities(&capabilities);
if (capabilities.MaxVersion < IORING_VERSION_3) // 3 adds write, flush and drain
return false;
if ((capabilities.FeatureFlags & IORING_FEATURE_SET_COMPLETION_EVENT) == 0)
@@ -75,7 +137,8 @@ bool QIORing::initializeIORing()
IORING_CREATE_FLAGS flags;
memset(&flags, 0, sizeof(flags));
- HRESULT hr = CreateIoRing(IORING_VERSION_3, flags, sqEntries, cqEntries, &ioRingHandle);
+ HRESULT hr = apiTable->CreateIoRing(IORING_VERSION_3, flags, sqEntries, cqEntries,
+ &ioRingHandle);
if (FAILED(hr)) {
qErrnoWarning(hr, "failed to initialize QIORing");
return false;
@@ -83,7 +146,7 @@ bool QIORing::initializeIORing()
auto earlyExitCleanup = qScopeGuard([this]() {
if (eventHandle != INVALID_HANDLE_VALUE)
CloseHandle(eventHandle);
- CloseIoRing(ioRingHandle);
+ apiTable->CloseIoRing(ioRingHandle);
});
eventHandle = CreateEvent(nullptr, TRUE, FALSE, nullptr);
if (eventHandle == INVALID_HANDLE_VALUE) {
@@ -91,13 +154,13 @@ bool QIORing::initializeIORing()
return false;
}
notifier.emplace(eventHandle);
- hr = SetIoRingCompletionEvent(ioRingHandle, eventHandle);
+ hr = apiTable->SetIoRingCompletionEvent(ioRingHandle, eventHandle);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to assign the event handle to QIORing");
return false;
}
IORING_INFO info;
- if (SUCCEEDED(GetIoRingInfo(ioRingHandle, &info))) {
+ if (SUCCEEDED(apiTable->GetIoRingInfo(ioRingHandle, &info))) {
sqEntries = info.SubmissionQueueSize;
cqEntries = info.CompletionQueueSize;
qCDebug(lcQIORing) << "QIORing configured with capacity for" << sqEntries
@@ -274,7 +337,7 @@ void QIORing::completionReady()
{
ResetEvent(eventHandle);
IORING_CQE entry;
- while (PopIoRingCompletion(ioRingHandle, &entry) == S_OK) {
+ while (apiTable->PopIoRingCompletion(ioRingHandle, &entry) == S_OK) {
// NOLINTNEXTLINE(performance-no-int-to-ptr)
auto *request = reinterpret_cast<GenericRequestType *>(entry.UserData);
if (!addrItMap.contains(request)) {
@@ -458,7 +521,8 @@ void QIORing::submitRequests()
const bool shouldTryWait = std::exchange(queueWasFull, false);
const auto submitToRing = [this, &shouldTryWait] {
quint32 submittedEntries = 0;
- HRESULT hr = SubmitIoRing(ioRingHandle, shouldTryWait ? 1 : 0, 1, &submittedEntries);
+ HRESULT hr = apiTable->SubmitIoRing(ioRingHandle, shouldTryWait ? 1 : 0, 1,
+ &submittedEntries);
qCDebug(lcQIORing) << "Submitted" << submittedEntries << "requests";
unstagedRequests -= submittedEntries;
if (FAILED(hr)) {
@@ -558,9 +622,9 @@ auto QIORing::prepareRequest(GenericRequestType &request) -> RequestPrepResult
auto *closeRequest = request.requestData<Operation::Close>();
// NOLINTNEXTLINE(performance-no-int-to-ptr)
const IORING_HANDLE_REF fileRef(HANDLE(closeRequest->fd));
- hr = BuildIoRingFlushFile(ioRingHandle, fileRef, FILE_FLUSH_MIN_METADATA,
- quintptr(std::addressof(request)),
- IOSQE_FLAGS_DRAIN_PRECEDING_OPS);
+ hr = apiTable->BuildIoRingFlushFile(ioRingHandle, fileRef, FILE_FLUSH_MIN_METADATA,
+ quintptr(std::addressof(request)),
+ IOSQE_FLAGS_DRAIN_PRECEDING_OPS);
break;
}
case Operation::Read: {
@@ -645,9 +709,9 @@ auto QIORing::prepareRequest(GenericRequestType &request) -> RequestPrepResult
auto *flushRequest = request.requestData<Operation::Flush>();
// NOLINTNEXTLINE(performance-no-int-to-ptr)
const IORING_HANDLE_REF fileRef(HANDLE(flushRequest->fd));
- hr = BuildIoRingFlushFile(ioRingHandle, fileRef, FILE_FLUSH_DEFAULT,
- quintptr(std::addressof(request)),
- IOSQE_FLAGS_DRAIN_PRECEDING_OPS);
+ hr = apiTable->BuildIoRingFlushFile(ioRingHandle, fileRef, FILE_FLUSH_DEFAULT,
+ quintptr(std::addressof(request)),
+ IOSQE_FLAGS_DRAIN_PRECEDING_OPS);
break;
}
case QtPrivate::Operation::Stat: {
@@ -703,8 +767,8 @@ auto QIORing::prepareRequest(GenericRequestType &request) -> RequestPrepResult
}
// NOLINTNEXTLINE(performance-no-int-to-ptr)
const IORING_HANDLE_REF fileRef((HANDLE(fd)));
- hr = BuildIoRingCancelRequest(ioRingHandle, fileRef, quintptr(otherOperation),
- quintptr(std::addressof(request)));
+ hr = apiTable->BuildIoRingCancelRequest(ioRingHandle, fileRef, quintptr(otherOperation),
+ quintptr(std::addressof(request)));
break;
}
case Operation::NumOperations:
diff --git a/src/corelib/io/qrandomaccessasyncfile.cpp b/src/corelib/io/qrandomaccessasyncfile.cpp
index c544585de9d..34e216efe27 100644
--- a/src/corelib/io/qrandomaccessasyncfile.cpp
+++ b/src/corelib/io/qrandomaccessasyncfile.cpp
@@ -7,6 +7,31 @@
QT_BEGIN_NAMESPACE
+QRandomAccessAsyncFileBackend::QRandomAccessAsyncFileBackend(QRandomAccessAsyncFile *owner)
+ : m_owner(owner)
+{
+}
+QRandomAccessAsyncFileBackend::~QRandomAccessAsyncFileBackend() = default;
+QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() = default;
+QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate() = default;
+
+void QRandomAccessAsyncFilePrivate::init()
+{
+ Q_Q(QRandomAccessAsyncFile);
+
+#if defined(QT_RANDOMACCESSASYNCFILE_QIORING) || defined(Q_OS_DARWIN)
+ m_backend = std::make_unique<QRandomAccessAsyncFileNativeBackend>(q);
+#endif
+ if (!m_backend || !m_backend->init()) {
+#if QT_CONFIG(thread) && QT_CONFIG(future)
+ m_backend = std::make_unique<QRandomAccessAsyncFileThreadPoolBackend>(q);
+ [[maybe_unused]]
+ bool result = m_backend->init();
+ Q_ASSERT(result); // it always succeeds
+#endif
+ }
+}
+
QRandomAccessAsyncFile::QRandomAccessAsyncFile(QObject *parent)
: QObject{*new QRandomAccessAsyncFilePrivate, parent}
{
diff --git a/src/corelib/io/qrandomaccessasyncfile_darwin.mm b/src/corelib/io/qrandomaccessasyncfile_darwin.mm
index fca225263ba..80c1affa642 100644
--- a/src/corelib/io/qrandomaccessasyncfile_darwin.mm
+++ b/src/corelib/io/qrandomaccessasyncfile_darwin.mm
@@ -27,14 +27,14 @@ static bool isBarrierOperation(QIOOperation::Type type)
// only!
template <typename Operation, typename ...Args>
Operation *
-QRandomAccessAsyncFilePrivate::addOperation(QIOOperation::Type type, qint64 offset, Args &&...args)
+QRandomAccessAsyncFileNativeBackend::addOperation(QIOOperation::Type type, qint64 offset, Args &&...args)
{
auto dataStorage = new QtPrivate::QIOOperationDataStorage(std::forward<Args>(args)...);
auto *priv = new QIOOperationPrivate(dataStorage);
priv->offset = offset;
priv->type = type;
- Operation *op = new Operation(*priv, q_ptr);
+ Operation *op = new Operation(*priv, m_owner);
auto opId = getNextId();
m_operations.push_back(OperationInfo(opId, op));
startOperationsUntilBarrier();
@@ -42,19 +42,20 @@ QRandomAccessAsyncFilePrivate::addOperation(QIOOperation::Type type, qint64 offs
return op;
}
-QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate()
- : QObjectPrivate()
+QRandomAccessAsyncFileNativeBackend::QRandomAccessAsyncFileNativeBackend(QRandomAccessAsyncFile *owner)
+ : QRandomAccessAsyncFileBackend(owner)
{
}
-QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate()
+QRandomAccessAsyncFileNativeBackend::~QRandomAccessAsyncFileNativeBackend()
= default;
-void QRandomAccessAsyncFilePrivate::init()
+bool QRandomAccessAsyncFileNativeBackend::init()
{
+ return true;
}
-void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
+void QRandomAccessAsyncFileNativeBackend::cancelAndWait(QIOOperation *op)
{
auto it = std::find_if(m_operations.cbegin(), m_operations.cend(),
[op](const auto &opInfo) {
@@ -87,7 +88,7 @@ void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
startOperationsUntilBarrier();
}
-void QRandomAccessAsyncFilePrivate::close()
+void QRandomAccessAsyncFileNativeBackend::close()
{
if (m_fileState == FileState::Closed)
return;
@@ -125,7 +126,7 @@ void QRandomAccessAsyncFilePrivate::close()
m_fileState = FileState::Closed;
}
-qint64 QRandomAccessAsyncFilePrivate::size() const
+qint64 QRandomAccessAsyncFileNativeBackend::size() const
{
if (m_fileState != FileState::Opened)
return -1;
@@ -138,7 +139,7 @@ qint64 QRandomAccessAsyncFilePrivate::size() const
}
QIOOperation *
-QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode mode)
+QRandomAccessAsyncFileNativeBackend::open(const QString &path, QIODeviceBase::OpenMode mode)
{
if (m_fileState == FileState::Closed) {
m_filePath = path;
@@ -151,44 +152,44 @@ QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode
return addOperation<QIOOperation>(QIOOperation::Type::Open, 0);
}
-QIOOperation *QRandomAccessAsyncFilePrivate::flush()
+QIOOperation *QRandomAccessAsyncFileNativeBackend::flush()
{
return addOperation<QIOOperation>(QIOOperation::Type::Flush, 0);
}
-QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxSize)
+QIOReadOperation *QRandomAccessAsyncFileNativeBackend::read(qint64 offset, qint64 maxSize)
{
QByteArray array(maxSize, Qt::Uninitialized);
return addOperation<QIOReadOperation>(QIOOperation::Type::Read, offset, std::move(array));
}
-QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
+QIOWriteOperation *QRandomAccessAsyncFileNativeBackend::write(qint64 offset, const QByteArray &data)
{
QByteArray copy = data;
return write(offset, std::move(copy));
}
-QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
+QIOWriteOperation *QRandomAccessAsyncFileNativeBackend::write(qint64 offset, QByteArray &&data)
{
return addOperation<QIOWriteOperation>(QIOOperation::Type::Write, offset, std::move(data));
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<std::byte> buffer)
+QRandomAccessAsyncFileNativeBackend::readInto(qint64 offset, QSpan<std::byte> buffer)
{
return addOperation<QIOVectoredReadOperation>(QIOOperation::Type::Read, offset,
QSpan<const QSpan<std::byte>>{buffer});
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const std::byte> buffer)
+QRandomAccessAsyncFileNativeBackend::writeFrom(qint64 offset, QSpan<const std::byte> buffer)
{
return addOperation<QIOVectoredWriteOperation>(QIOOperation::Type::Write, offset,
QSpan<const QSpan<const std::byte>>{buffer});
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
+QRandomAccessAsyncFileNativeBackend::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
{
// GCD implementation does not have vectored read. Spawning several read
// operations (each with an updated offset), is not ideal, because some
@@ -202,12 +203,12 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::by
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
+QRandomAccessAsyncFileNativeBackend::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
{
return addOperation<QIOVectoredWriteOperation>(QIOOperation::Type::Write, offset, buffers);
}
-void QRandomAccessAsyncFilePrivate::notifyIfOperationsAreCompleted()
+void QRandomAccessAsyncFileNativeBackend::notifyIfOperationsAreCompleted()
{
QMutexLocker locker(&m_mutex);
--m_numChannelsToClose;
@@ -217,7 +218,7 @@ void QRandomAccessAsyncFilePrivate::notifyIfOperationsAreCompleted()
}
}
-dispatch_io_t QRandomAccessAsyncFilePrivate::createMainChannel(int fd)
+dispatch_io_t QRandomAccessAsyncFileNativeBackend::createMainChannel(int fd)
{
auto sharedThis = this;
auto channel =
@@ -235,7 +236,7 @@ dispatch_io_t QRandomAccessAsyncFilePrivate::createMainChannel(int fd)
return channel;
}
-dispatch_io_t QRandomAccessAsyncFilePrivate::duplicateIoChannel(OperationId opId)
+dispatch_io_t QRandomAccessAsyncFileNativeBackend::duplicateIoChannel(OperationId opId)
{
if (!m_ioChannel)
return nullptr;
@@ -258,13 +259,13 @@ dispatch_io_t QRandomAccessAsyncFilePrivate::duplicateIoChannel(OperationId opId
return channel;
}
-void QRandomAccessAsyncFilePrivate::closeIoChannel(dispatch_io_t channel)
+void QRandomAccessAsyncFileNativeBackend::closeIoChannel(dispatch_io_t channel)
{
if (channel)
dispatch_io_close(channel, DISPATCH_IO_STOP);
}
-void QRandomAccessAsyncFilePrivate::releaseIoChannel(dispatch_io_t channel)
+void QRandomAccessAsyncFileNativeBackend::releaseIoChannel(dispatch_io_t channel)
{
if (channel) {
dispatch_release(channel);
@@ -272,7 +273,7 @@ void QRandomAccessAsyncFilePrivate::releaseIoChannel(dispatch_io_t channel)
}
}
-void QRandomAccessAsyncFilePrivate::handleOperationComplete(const OperationResult &opResult)
+void QRandomAccessAsyncFileNativeBackend::handleOperationComplete(const OperationResult &opResult)
{
// try to start next operations on return
auto onReturn = qScopeGuard([this] {
@@ -379,15 +380,15 @@ void QRandomAccessAsyncFilePrivate::handleOperationComplete(const OperationResul
}
}
-void QRandomAccessAsyncFilePrivate::queueCompletion(OperationId opId, int error)
+void QRandomAccessAsyncFileNativeBackend::queueCompletion(OperationId opId, int error)
{
const OperationResult res = { opId, 0LL, error };
- QMetaObject::invokeMethod(q_ptr, [this, res] {
+ QMetaObject::invokeMethod(m_owner, [this, res] {
handleOperationComplete(res);
}, Qt::QueuedConnection);
}
-void QRandomAccessAsyncFilePrivate::startOperationsUntilBarrier()
+void QRandomAccessAsyncFileNativeBackend::startOperationsUntilBarrier()
{
// starts all operations until barrier, or a barrier operation if it's the
// first one
@@ -421,7 +422,7 @@ void QRandomAccessAsyncFilePrivate::startOperationsUntilBarrier()
}
}
-void QRandomAccessAsyncFilePrivate::executeRead(OperationInfo &opInfo)
+void QRandomAccessAsyncFileNativeBackend::executeRead(OperationInfo &opInfo)
{
opInfo.channel = duplicateIoChannel(opInfo.opId);
if (!opInfo.channel) {
@@ -452,7 +453,7 @@ void QRandomAccessAsyncFilePrivate::executeRead(OperationInfo &opInfo)
}
}
-void QRandomAccessAsyncFilePrivate::executeWrite(OperationInfo &opInfo)
+void QRandomAccessAsyncFileNativeBackend::executeWrite(OperationInfo &opInfo)
{
opInfo.channel = duplicateIoChannel(opInfo.opId);
if (!opInfo.channel) {
@@ -501,7 +502,7 @@ void QRandomAccessAsyncFilePrivate::executeWrite(OperationInfo &opInfo)
}
}
-void QRandomAccessAsyncFilePrivate::executeFlush(OperationInfo &opInfo)
+void QRandomAccessAsyncFileNativeBackend::executeFlush(OperationInfo &opInfo)
{
opInfo.channel = duplicateIoChannel(opInfo.opId);
if (!opInfo.channel) {
@@ -530,7 +531,7 @@ void QRandomAccessAsyncFilePrivate::executeFlush(OperationInfo &opInfo)
}
}
} else {
- auto context = sharedThis->q_ptr;
+ auto context = sharedThis->m_owner;
const OperationResult res = { opId, 0LL, err };
QMetaObject::invokeMethod(context, [sharedThis](const OperationResult &r) {
sharedThis->handleOperationComplete(r);
@@ -562,7 +563,7 @@ static inline int openModeToOpenFlags(QIODevice::OpenMode mode)
return oflags;
}
-void QRandomAccessAsyncFilePrivate::executeOpen(OperationInfo &opInfo)
+void QRandomAccessAsyncFileNativeBackend::executeOpen(OperationInfo &opInfo)
{
if (m_fileState != FileState::OpenPending) {
queueCompletion(opInfo.opId, EINVAL);
@@ -603,7 +604,7 @@ void QRandomAccessAsyncFilePrivate::executeOpen(OperationInfo &opInfo)
Q_ASSERT(sharedThis->m_numChannelsToClose == 0);
sharedThis->m_cancellationCondition.wakeOne();
} else {
- auto context = sharedThis->q_ptr;
+ auto context = sharedThis->m_owner;
const OperationResult res = { opId, qint64(fd), err };
QMetaObject::invokeMethod(context,
[sharedThis](const OperationResult &r) {
@@ -613,7 +614,7 @@ void QRandomAccessAsyncFilePrivate::executeOpen(OperationInfo &opInfo)
});
}
-void QRandomAccessAsyncFilePrivate::readOneBuffer(OperationId opId, qsizetype bufferIdx,
+void QRandomAccessAsyncFileNativeBackend::readOneBuffer(OperationId opId, qsizetype bufferIdx,
qint64 alreadyRead)
{
// we need to lookup the operation again, because it could have beed removed
@@ -650,7 +651,7 @@ void QRandomAccessAsyncFilePrivate::readOneBuffer(OperationId opId, qsizetype bu
readBuffers.size(), alreadyRead);
}
-void QRandomAccessAsyncFilePrivate::readOneBufferHelper(OperationId opId, dispatch_io_t channel,
+void QRandomAccessAsyncFileNativeBackend::readOneBufferHelper(OperationId opId, dispatch_io_t channel,
qint64 offset, void *bytesPtr,
qint64 maxSize, qsizetype currentBufferIdx,
qsizetype totalBuffers, qint64 alreadyRead)
@@ -698,7 +699,7 @@ void QRandomAccessAsyncFilePrivate::readOneBufferHelper(OperationId opId, dispat
}
} else {
sharedThis->m_runningOps.remove(opId);
- auto context = sharedThis->q_ptr;
+ auto context = sharedThis->m_owner;
// if error, or last buffer, or read less than expected,
// report operation completion
qint64 totalRead = qint64(readFromBuffer) + alreadyRead;
@@ -721,7 +722,7 @@ void QRandomAccessAsyncFilePrivate::readOneBufferHelper(OperationId opId, dispat
});
}
-void QRandomAccessAsyncFilePrivate::writeHelper(OperationId opId, dispatch_io_t channel,
+void QRandomAccessAsyncFileNativeBackend::writeHelper(OperationId opId, dispatch_io_t channel,
qint64 offset, dispatch_data_t dataToWrite,
qint64 dataSize)
{
@@ -760,7 +761,7 @@ void QRandomAccessAsyncFilePrivate::writeHelper(OperationId opId, dispatch_io_t
const size_t written = dataSize - toBeWritten;
[dataToWrite release];
- auto context = sharedThis->q_ptr;
+ auto context = sharedThis->m_owner;
const OperationResult res = { opId, qint64(written), error };
QMetaObject::invokeMethod(context,
[sharedThis](const OperationResult &r) {
@@ -770,7 +771,7 @@ void QRandomAccessAsyncFilePrivate::writeHelper(OperationId opId, dispatch_io_t
});
}
-QRandomAccessAsyncFilePrivate::OperationId QRandomAccessAsyncFilePrivate::getNextId()
+QRandomAccessAsyncFileNativeBackend::OperationId QRandomAccessAsyncFileNativeBackend::getNextId()
{
// never return reserved values
static OperationId opId = kInvalidOperationId;
diff --git a/src/corelib/io/qrandomaccessasyncfile_p_p.h b/src/corelib/io/qrandomaccessasyncfile_p_p.h
index 11ad788c884..2eb53058780 100644
--- a/src/corelib/io/qrandomaccessasyncfile_p_p.h
+++ b/src/corelib/io/qrandomaccessasyncfile_p_p.h
@@ -22,7 +22,7 @@
#include <QtCore/qstring.h>
-#ifdef QT_RANDOMACCESSASYNCFILE_THREAD
+#if QT_CONFIG(future) && QT_CONFIG(thread)
#include <QtCore/private/qfsfileengine_p.h>
@@ -30,7 +30,7 @@
#include <QtCore/qmutex.h>
#include <QtCore/qqueue.h>
-#endif // QT_RANDOMACCESSASYNCFILE_THREAD
+#endif // future && thread
#ifdef Q_OS_DARWIN
@@ -50,41 +50,36 @@
QT_BEGIN_NAMESPACE
-class QRandomAccessAsyncFilePrivate : public QObjectPrivate
+class QRandomAccessAsyncFileBackend
{
- Q_DECLARE_PUBLIC(QRandomAccessAsyncFile)
- Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFilePrivate)
+ Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFileBackend)
public:
- QRandomAccessAsyncFilePrivate();
- ~QRandomAccessAsyncFilePrivate() override;
-
- static QRandomAccessAsyncFilePrivate *get(QRandomAccessAsyncFile *file)
- { return file->d_func(); }
+ explicit QRandomAccessAsyncFileBackend(QRandomAccessAsyncFile *owner);
+ virtual ~QRandomAccessAsyncFileBackend();
- void init();
- void cancelAndWait(QIOOperation *op);
+ virtual bool init() = 0;
+ virtual void cancelAndWait(QIOOperation *op) = 0;
- void close();
- qint64 size() const;
+ virtual void close() = 0;
+ virtual qint64 size() const = 0;
- [[nodiscard]] QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode);
- [[nodiscard]] QIOOperation *flush();
+ [[nodiscard]] virtual QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode) = 0;
+ [[nodiscard]] virtual QIOOperation *flush() = 0;
- [[nodiscard]] QIOReadOperation *read(qint64 offset, qint64 maxSize);
- [[nodiscard]] QIOWriteOperation *write(qint64 offset, const QByteArray &data);
- [[nodiscard]] QIOWriteOperation *write(qint64 offset, QByteArray &&data);
+ [[nodiscard]] virtual QIOReadOperation *read(qint64 offset, qint64 maxSize) = 0;
+ [[nodiscard]] virtual QIOWriteOperation *write(qint64 offset, const QByteArray &data) = 0;
+ [[nodiscard]] virtual QIOWriteOperation *write(qint64 offset, QByteArray &&data) = 0;
- [[nodiscard]] QIOVectoredReadOperation *
- readInto(qint64 offset, QSpan<std::byte> buffer);
- [[nodiscard]] QIOVectoredWriteOperation *
- writeFrom(qint64 offset, QSpan<const std::byte> buffer);
-
- [[nodiscard]] QIOVectoredReadOperation *
- readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers);
- [[nodiscard]] QIOVectoredWriteOperation *
- writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers);
+ [[nodiscard]] virtual QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<std::byte> buffer) = 0;
+ [[nodiscard]] virtual QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const std::byte> buffer) = 0;
-private:
+ [[nodiscard]] virtual QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers) = 0;
+ [[nodiscard]] virtual QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers) = 0;
+protected:
// common for all backends
enum class FileState : quint8
{
@@ -94,32 +89,131 @@ private:
};
QString m_filePath;
+ QRandomAccessAsyncFile *m_owner = nullptr;
QIODeviceBase::OpenMode m_openMode;
FileState m_fileState = FileState::Closed;
+};
-#ifdef QT_RANDOMACCESSASYNCFILE_THREAD
+class QRandomAccessAsyncFilePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QRandomAccessAsyncFile)
+ Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFilePrivate)
public:
- struct OperationResult
+ QRandomAccessAsyncFilePrivate();
+ ~QRandomAccessAsyncFilePrivate() override;
+
+ static QRandomAccessAsyncFilePrivate *get(QRandomAccessAsyncFile *file)
+ { return file->d_func(); }
+
+ void init();
+ void cancelAndWait(QIOOperation *op)
{
- qint64 bytesProcessed; // either read or written
- QIOOperation::Error error;
- };
+ checkValid();
+ m_backend->cancelAndWait(op);
+ }
+
+ void close()
+ {
+ checkValid();
+ m_backend->close();
+ }
+ qint64 size() const
+ {
+ checkValid();
+ return m_backend->size();
+ }
+
+ [[nodiscard]] QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode)
+ {
+ checkValid();
+ return m_backend->open(path, mode);
+ }
+ [[nodiscard]] QIOOperation *flush()
+ {
+ checkValid();
+ return m_backend->flush();
+ }
+
+ [[nodiscard]] QIOReadOperation *read(qint64 offset, qint64 maxSize)
+ {
+ checkValid();
+ return m_backend->read(offset, maxSize);
+ }
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, const QByteArray &data)
+ {
+ checkValid();
+ return m_backend->write(offset, data);
+ }
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, QByteArray &&data)
+ {
+ checkValid();
+ return m_backend->write(offset, std::move(data));
+ }
+
+ [[nodiscard]] QIOVectoredReadOperation *readInto(qint64 offset, QSpan<std::byte> buffer)
+ {
+ checkValid();
+ return m_backend->readInto(offset, buffer);
+ }
+ [[nodiscard]] QIOVectoredWriteOperation *writeFrom(qint64 offset, QSpan<const std::byte> buffer)
+ {
+ checkValid();
+ return m_backend->writeFrom(offset, buffer);
+ }
+
+ [[nodiscard]] QIOVectoredReadOperation *readInto(qint64 offset,
+ QSpan<const QSpan<std::byte>> buffers)
+ {
+ checkValid();
+ return m_backend->readInto(offset, buffers);
+ }
+ [[nodiscard]] QIOVectoredWriteOperation *writeFrom(qint64 offset,
+ QSpan<const QSpan<const std::byte>> buffers)
+ {
+ checkValid();
+ return m_backend->writeFrom(offset, buffers);
+ }
private:
- mutable QBasicMutex m_engineMutex;
- std::unique_ptr<QFSFileEngine> m_engine;
- QFutureWatcher<OperationResult> m_watcher;
+ void checkValid() const { Q_ASSERT(m_backend); }
+ std::unique_ptr<QRandomAccessAsyncFileBackend> m_backend;
- QQueue<QPointer<QIOOperation>> m_operations;
- QPointer<QIOOperation> m_currentOperation;
- qsizetype numProcessedBuffers = 0;
+};
- void executeNextOperation();
- void processBufferAt(qsizetype idx);
- void processFlush();
- void processOpen();
- void operationComplete();
-#elif defined(QT_RANDOMACCESSASYNCFILE_QIORING)
+
+#if defined(QT_RANDOMACCESSASYNCFILE_QIORING) || defined(Q_OS_DARWIN)
+class QRandomAccessAsyncFileNativeBackend final : public QRandomAccessAsyncFileBackend
+{
+ Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFileNativeBackend)
+public:
+ explicit QRandomAccessAsyncFileNativeBackend(QRandomAccessAsyncFile *owner);
+ ~QRandomAccessAsyncFileNativeBackend();
+
+ bool init() override;
+ void cancelAndWait(QIOOperation *op) override;
+
+ void close() override;
+ qint64 size() const override;
+
+ [[nodiscard]] QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode) override;
+ [[nodiscard]] QIOOperation *flush() override;
+
+ [[nodiscard]] QIOReadOperation *read(qint64 offset, qint64 maxSize) override;
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, const QByteArray &data) override;
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, QByteArray &&data) override;
+
+ [[nodiscard]] QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<std::byte> buffer) override;
+ [[nodiscard]] QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const std::byte> buffer) override;
+
+ [[nodiscard]] QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers) override;
+ [[nodiscard]] QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers) override;
+
+private:
+#if defined(QT_RANDOMACCESSASYNCFILE_QIORING)
void queueCompletion(QIOOperationPrivate *priv, QIOOperation::Error error);
void startReadIntoSingle(QIOOperation *op, const QSpan<std::byte> &to);
void startWriteFromSingle(QIOOperation *op, const QSpan<const std::byte> &from);
@@ -210,6 +304,61 @@ private:
dispatch_data_t dataToWrite, qint64 dataSize);
#endif
};
+#endif // QIORing || macOS
+
+#if QT_CONFIG(future) && QT_CONFIG(thread)
+class QRandomAccessAsyncFileThreadPoolBackend : public QRandomAccessAsyncFileBackend
+{
+ Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFileThreadPoolBackend)
+public:
+ explicit QRandomAccessAsyncFileThreadPoolBackend(QRandomAccessAsyncFile *owner);
+ ~QRandomAccessAsyncFileThreadPoolBackend();
+
+ bool init() override;
+ void cancelAndWait(QIOOperation *op) override;
+
+ void close() override;
+ qint64 size() const override;
+
+ [[nodiscard]] QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode) override;
+ [[nodiscard]] QIOOperation *flush() override;
+
+ [[nodiscard]] QIOReadOperation *read(qint64 offset, qint64 maxSize) override;
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, const QByteArray &data) override;
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, QByteArray &&data) override;
+
+ [[nodiscard]] QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<std::byte> buffer) override;
+ [[nodiscard]] QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const std::byte> buffer) override;
+
+ [[nodiscard]] QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers) override;
+ [[nodiscard]] QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers) override;
+
+ struct OperationResult
+ {
+ qint64 bytesProcessed; // either read or written
+ QIOOperation::Error error;
+ };
+private:
+
+ mutable QBasicMutex m_engineMutex;
+ std::unique_ptr<QFSFileEngine> m_engine;
+ QFutureWatcher<OperationResult> m_watcher;
+
+ QQueue<QPointer<QIOOperation>> m_operations;
+ QPointer<QIOOperation> m_currentOperation;
+ qsizetype numProcessedBuffers = 0;
+
+ void executeNextOperation();
+ void processBufferAt(qsizetype idx);
+ void processFlush();
+ void processOpen();
+ void operationComplete();
+};
+#endif // future && thread
QT_END_NAMESPACE
diff --git a/src/corelib/io/qrandomaccessasyncfile_qioring.cpp b/src/corelib/io/qrandomaccessasyncfile_qioring.cpp
index c9783ea2856..8e1145325d8 100644
--- a/src/corelib/io/qrandomaccessasyncfile_qioring.cpp
+++ b/src/corelib/io/qrandomaccessasyncfile_qioring.cpp
@@ -18,18 +18,21 @@ QT_BEGIN_NAMESPACE
Q_STATIC_LOGGING_CATEGORY(lcQRandomAccessIORing, "qt.core.qrandomaccessasyncfile.ioring",
QtCriticalMsg);
-QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() = default;
+QRandomAccessAsyncFileNativeBackend::QRandomAccessAsyncFileNativeBackend(QRandomAccessAsyncFile *owner)
+ : QRandomAccessAsyncFileBackend(owner)
+{}
-QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate() = default;
+QRandomAccessAsyncFileNativeBackend::~QRandomAccessAsyncFileNativeBackend() = default;
-void QRandomAccessAsyncFilePrivate::init()
+bool QRandomAccessAsyncFileNativeBackend::init()
{
m_ioring = QIORing::sharedInstance();
if (!m_ioring)
- qCCritical(lcQRandomAccessIORing, "QRandomAccessAsyncFile: ioring failed to initialize");
+ qCWarning(lcQRandomAccessIORing, "QRandomAccessAsyncFile: ioring failed to initialize");
+ return m_ioring != nullptr;
}
-QIORing::RequestHandle QRandomAccessAsyncFilePrivate::cancel(QIORing::RequestHandle handle)
+QIORing::RequestHandle QRandomAccessAsyncFileNativeBackend::cancel(QIORing::RequestHandle handle)
{
if (handle) {
QIORingRequest<QIORing::Operation::Cancel> cancelRequest;
@@ -39,7 +42,7 @@ QIORing::RequestHandle QRandomAccessAsyncFilePrivate::cancel(QIORing::RequestHan
return nullptr;
}
-void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
+void QRandomAccessAsyncFileNativeBackend::cancelAndWait(QIOOperation *op)
{
auto *opHandle = m_opHandleMap.value(op);
if (auto *handle = cancel(opHandle)) {
@@ -48,7 +51,7 @@ void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
}
}
-void QRandomAccessAsyncFilePrivate::queueCompletion(QIOOperationPrivate *priv, QIOOperation::Error error)
+void QRandomAccessAsyncFileNativeBackend::queueCompletion(QIOOperationPrivate *priv, QIOOperation::Error error)
{
// Remove the handle now in case the user cancels or deletes the io-operation
// before operationComplete is called - the null-handle will protect from
@@ -61,14 +64,14 @@ void QRandomAccessAsyncFilePrivate::queueCompletion(QIOOperationPrivate *priv, Q
}, Qt::QueuedConnection);
}
-QIOOperation *QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode mode)
+QIOOperation *QRandomAccessAsyncFileNativeBackend::open(const QString &path, QIODeviceBase::OpenMode mode)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage();
auto *priv = new QIOOperationPrivate(dataStorage);
priv->type = QIOOperation::Type::Open;
- auto *op = new QIOOperation(*priv, q_ptr);
+ auto *op = new QIOOperation(*priv, m_owner);
if (m_fileState != FileState::Closed) {
queueCompletion(priv, QIOOperation::Error::Open);
return op;
@@ -115,7 +118,7 @@ QIOOperation *QRandomAccessAsyncFilePrivate::open(const QString &path, QIODevice
return op;
}
-void QRandomAccessAsyncFilePrivate::close()
+void QRandomAccessAsyncFileNativeBackend::close()
{
// all the operations should be aborted
const auto ops = std::exchange(m_operations, {});
@@ -123,7 +126,7 @@ void QRandomAccessAsyncFilePrivate::close()
// Request to cancel all of the in-flight operations:
for (const auto &op : ops) {
if (op) {
- op->d_func()->error = QIOOperation::Error::Aborted;
+ QIOOperationPrivate::get(op)->error = QIOOperation::Error::Aborted;
if (auto *opHandle = m_opHandleMap.value(op)) {
tasksToAwait.append(cancel(opHandle));
tasksToAwait.append(opHandle);
@@ -142,7 +145,7 @@ void QRandomAccessAsyncFilePrivate::close()
m_fd = -1;
}
-qint64 QRandomAccessAsyncFilePrivate::size() const
+qint64 QRandomAccessAsyncFileNativeBackend::size() const
{
QIORingRequest<QIORing::Operation::Stat> statRequest;
statRequest.fd = m_fd;
@@ -161,14 +164,14 @@ qint64 QRandomAccessAsyncFilePrivate::size() const
return finalSize;
}
-QIOOperation *QRandomAccessAsyncFilePrivate::flush()
+QIOOperation *QRandomAccessAsyncFileNativeBackend::flush()
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage();
auto *priv = new QIOOperationPrivate(dataStorage);
priv->type = QIOOperation::Type::Flush;
- auto *op = new QIOOperation(*priv, q_ptr);
+ auto *op = new QIOOperation(*priv, m_owner);
m_operations.append(op);
QIORingRequest<QIORing::Operation::Flush> flushRequest;
@@ -192,7 +195,7 @@ QIOOperation *QRandomAccessAsyncFilePrivate::flush()
return op;
}
-void QRandomAccessAsyncFilePrivate::startReadIntoSingle(QIOOperation *op,
+void QRandomAccessAsyncFileNativeBackend::startReadIntoSingle(QIOOperation *op,
const QSpan<std::byte> &to)
{
QIORingRequest<QIORing::Operation::Read> readRequest;
@@ -231,7 +234,7 @@ void QRandomAccessAsyncFilePrivate::startReadIntoSingle(QIOOperation *op,
m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(readRequest)));
}
-QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxSize)
+QIOReadOperation *QRandomAccessAsyncFileNativeBackend::read(qint64 offset, qint64 maxSize)
{
QByteArray array;
array.resizeForOverwrite(maxSize);
@@ -241,7 +244,7 @@ QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxS
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOReadOperation(*priv, q_ptr);
+ auto *op = new QIOReadOperation(*priv, m_owner);
m_operations.append(op);
startReadIntoSingle(op, as_writable_bytes(QSpan(dataStorage->getByteArray())));
@@ -249,12 +252,12 @@ QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxS
return op;
}
-QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
+QIOWriteOperation *QRandomAccessAsyncFileNativeBackend::write(qint64 offset, const QByteArray &data)
{
return write(offset, QByteArray(data));
}
-void QRandomAccessAsyncFilePrivate::startWriteFromSingle(QIOOperation *op,
+void QRandomAccessAsyncFileNativeBackend::startWriteFromSingle(QIOOperation *op,
const QSpan<const std::byte> &from)
{
QIORingRequest<QIORing::Operation::Write> writeRequest;
@@ -288,7 +291,7 @@ void QRandomAccessAsyncFilePrivate::startWriteFromSingle(QIOOperation *op,
m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(writeRequest)));
}
-QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
+QIOWriteOperation *QRandomAccessAsyncFileNativeBackend::write(qint64 offset, QByteArray &&data)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(std::move(data));
@@ -296,7 +299,7 @@ QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArra
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOWriteOperation(*priv, q_ptr);
+ auto *op = new QIOWriteOperation(*priv, m_owner);
m_operations.append(op);
startWriteFromSingle(op, as_bytes(QSpan(dataStorage->getByteArray())));
@@ -304,7 +307,7 @@ QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArra
return op;
}
-QIOVectoredReadOperation *QRandomAccessAsyncFilePrivate::readInto(qint64 offset,
+QIOVectoredReadOperation *QRandomAccessAsyncFileNativeBackend::readInto(qint64 offset,
QSpan<std::byte> buffer)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(
@@ -314,7 +317,7 @@ QIOVectoredReadOperation *QRandomAccessAsyncFilePrivate::readInto(qint64 offset,
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredReadOperation(*priv, m_owner);
m_operations.append(op);
startReadIntoSingle(op, dataStorage->getReadSpans().first());
@@ -322,7 +325,7 @@ QIOVectoredReadOperation *QRandomAccessAsyncFilePrivate::readInto(qint64 offset,
return op;
}
-QIOVectoredWriteOperation *QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset,
+QIOVectoredWriteOperation *QRandomAccessAsyncFileNativeBackend::writeFrom(qint64 offset,
QSpan<const std::byte> buffer)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(
@@ -332,7 +335,7 @@ QIOVectoredWriteOperation *QRandomAccessAsyncFilePrivate::writeFrom(qint64 offse
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredWriteOperation(*priv, m_owner);
m_operations.append(op);
startWriteFromSingle(op, dataStorage->getWriteSpans().first());
@@ -341,7 +344,7 @@ QIOVectoredWriteOperation *QRandomAccessAsyncFilePrivate::writeFrom(qint64 offse
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
+QRandomAccessAsyncFileNativeBackend::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
{
if (!QIORing::supportsOperation(QtPrivate::Operation::VectoredRead))
return nullptr;
@@ -351,7 +354,7 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::by
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredReadOperation(*priv, m_owner);
if (priv->offset < 0) { // The QIORing offset is unsigned, so error out now
queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
return op;
@@ -393,7 +396,7 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::by
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
+QRandomAccessAsyncFileNativeBackend::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
{
if (!QIORing::supportsOperation(QtPrivate::Operation::VectoredWrite))
return nullptr;
@@ -403,7 +406,7 @@ QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredWriteOperation(*priv, m_owner);
if (priv->offset < 0) { // The QIORing offset is unsigned, so error out now
queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
return op;
diff --git a/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp b/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
index 4ebcf554655..774fbadc5ad 100644
--- a/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
+++ b/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
@@ -64,28 +64,29 @@ static SharedThreadPool asyncFileThreadPool;
} // anonymous namespace
-QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() :
- QObjectPrivate()
+QRandomAccessAsyncFileThreadPoolBackend::QRandomAccessAsyncFileThreadPoolBackend(QRandomAccessAsyncFile *owner) :
+ QRandomAccessAsyncFileBackend(owner)
{
asyncFileThreadPool.ref();
}
-QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate()
+QRandomAccessAsyncFileThreadPoolBackend::~QRandomAccessAsyncFileThreadPoolBackend()
{
asyncFileThreadPool.deref();
}
-void QRandomAccessAsyncFilePrivate::init()
+bool QRandomAccessAsyncFileThreadPoolBackend::init()
{
- QObject::connect(&m_watcher, &QFutureWatcherBase::finished, q_ptr, [this]{
+ QObject::connect(&m_watcher, &QFutureWatcherBase::finished, m_owner, [this]{
operationComplete();
});
- QObject::connect(&m_watcher, &QFutureWatcherBase::canceled, q_ptr, [this]{
+ QObject::connect(&m_watcher, &QFutureWatcherBase::canceled, m_owner, [this]{
operationComplete();
});
+ return true;
}
-void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
+void QRandomAccessAsyncFileThreadPoolBackend::cancelAndWait(QIOOperation *op)
{
if (op == m_currentOperation) {
m_currentOperation = nullptr; // to discard the result
@@ -97,7 +98,7 @@ void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
}
QIOOperation *
-QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode mode)
+QRandomAccessAsyncFileThreadPoolBackend::open(const QString &path, QIODeviceBase::OpenMode mode)
{
// We generate the command in any case. But if the file is already opened,
// it will finish with an error
@@ -112,14 +113,14 @@ QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode
auto *priv = new QIOOperationPrivate(dataStorage);
priv->type = QIOOperation::Type::Open;
- auto *op = new QIOOperation(*priv, q_ptr);
+ auto *op = new QIOOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
-void QRandomAccessAsyncFilePrivate::close()
+void QRandomAccessAsyncFileThreadPoolBackend::close()
{
// all the operations should be aborted
for (const auto &op : std::as_const(m_operations)) {
@@ -148,7 +149,7 @@ void QRandomAccessAsyncFilePrivate::close()
m_fileState = FileState::Closed;
}
-qint64 QRandomAccessAsyncFilePrivate::size() const
+qint64 QRandomAccessAsyncFileThreadPoolBackend::size() const
{
QMutexLocker locker(&m_engineMutex);
if (m_engine)
@@ -156,20 +157,20 @@ qint64 QRandomAccessAsyncFilePrivate::size() const
return -1;
}
-QIOOperation *QRandomAccessAsyncFilePrivate::flush()
+QIOOperation *QRandomAccessAsyncFileThreadPoolBackend::flush()
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage();
auto *priv = new QIOOperationPrivate(dataStorage);
priv->type = QIOOperation::Type::Flush;
- auto *op = new QIOOperation(*priv, q_ptr);
+ auto *op = new QIOOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
-QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxSize)
+QIOReadOperation *QRandomAccessAsyncFileThreadPoolBackend::read(qint64 offset, qint64 maxSize)
{
QByteArray array;
array.resizeForOverwrite(maxSize);
@@ -179,14 +180,14 @@ QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxS
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOReadOperation(*priv, q_ptr);
+ auto *op = new QIOReadOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOWriteOperation *
-QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
+QRandomAccessAsyncFileThreadPoolBackend::write(qint64 offset, const QByteArray &data)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(data);
@@ -194,14 +195,14 @@ QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOWriteOperation(*priv, q_ptr);
+ auto *op = new QIOWriteOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOWriteOperation *
-QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
+QRandomAccessAsyncFileThreadPoolBackend::write(qint64 offset, QByteArray &&data)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(std::move(data));
@@ -209,14 +210,14 @@ QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOWriteOperation(*priv, q_ptr);
+ auto *op = new QIOWriteOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<std::byte> buffer)
+QRandomAccessAsyncFileThreadPoolBackend::readInto(qint64 offset, QSpan<std::byte> buffer)
{
auto *dataStorage =
new QtPrivate::QIOOperationDataStorage(QSpan<const QSpan<std::byte>>{buffer});
@@ -225,14 +226,14 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<std::byte> buffer)
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredReadOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const std::byte> buffer)
+QRandomAccessAsyncFileThreadPoolBackend::writeFrom(qint64 offset, QSpan<const std::byte> buffer)
{
auto *dataStorage =
new QtPrivate::QIOOperationDataStorage(QSpan<const QSpan<const std::byte>>{buffer});
@@ -241,14 +242,14 @@ QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const std::byte> b
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredWriteOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
+QRandomAccessAsyncFileThreadPoolBackend::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(buffers);
@@ -256,14 +257,14 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::by
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredReadOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
+QRandomAccessAsyncFileThreadPoolBackend::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(buffers);
@@ -271,16 +272,16 @@ QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredWriteOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
-static QRandomAccessAsyncFilePrivate::OperationResult
+static QRandomAccessAsyncFileThreadPoolBackend::OperationResult
executeRead(QFSFileEngine *engine, QBasicMutex *mutex, qint64 offset, char *buffer, qint64 maxSize)
{
- QRandomAccessAsyncFilePrivate::OperationResult result{0, QIOOperation::Error::None};
+ QRandomAccessAsyncFileThreadPoolBackend::OperationResult result{0, QIOOperation::Error::None};
QMutexLocker locker(mutex);
if (engine) {
@@ -299,11 +300,11 @@ executeRead(QFSFileEngine *engine, QBasicMutex *mutex, qint64 offset, char *buff
return result;
}
-static QRandomAccessAsyncFilePrivate::OperationResult
+static QRandomAccessAsyncFileThreadPoolBackend::OperationResult
executeWrite(QFSFileEngine *engine, QBasicMutex *mutex, qint64 offset,
const char *buffer, qint64 size)
{
- QRandomAccessAsyncFilePrivate::OperationResult result{0, QIOOperation::Error::None};
+ QRandomAccessAsyncFileThreadPoolBackend::OperationResult result{0, QIOOperation::Error::None};
QMutexLocker locker(mutex);
if (engine) {
@@ -322,7 +323,7 @@ executeWrite(QFSFileEngine *engine, QBasicMutex *mutex, qint64 offset,
return result;
}
-void QRandomAccessAsyncFilePrivate::executeNextOperation()
+void QRandomAccessAsyncFileThreadPoolBackend::executeNextOperation()
{
if (m_currentOperation.isNull()) {
// start next
@@ -351,7 +352,7 @@ void QRandomAccessAsyncFilePrivate::executeNextOperation()
}
}
-void QRandomAccessAsyncFilePrivate::processBufferAt(qsizetype idx)
+void QRandomAccessAsyncFileThreadPoolBackend::processBufferAt(qsizetype idx)
{
Q_ASSERT(!m_currentOperation.isNull());
auto *priv = QIOOperationPrivate::get(m_currentOperation.get());
@@ -417,7 +418,7 @@ void QRandomAccessAsyncFilePrivate::processBufferAt(qsizetype idx)
}
}
-void QRandomAccessAsyncFilePrivate::processFlush()
+void QRandomAccessAsyncFileThreadPoolBackend::processFlush()
{
Q_ASSERT(!m_currentOperation.isNull());
auto *priv = QIOOperationPrivate::get(m_currentOperation.get());
@@ -427,7 +428,7 @@ void QRandomAccessAsyncFilePrivate::processFlush()
QBasicMutex *mutexPtr = &m_engineMutex;
auto op = [engine = m_engine.get(), mutexPtr] {
QMutexLocker locker(mutexPtr);
- QRandomAccessAsyncFilePrivate::OperationResult result{0, QIOOperation::Error::None};
+ QRandomAccessAsyncFileThreadPoolBackend::OperationResult result{0, QIOOperation::Error::None};
if (engine) {
if (!engine->flush())
result.error = QIOOperation::Error::Flush;
@@ -442,7 +443,7 @@ void QRandomAccessAsyncFilePrivate::processFlush()
m_watcher.setFuture(f);
}
-void QRandomAccessAsyncFilePrivate::processOpen()
+void QRandomAccessAsyncFileThreadPoolBackend::processOpen()
{
Q_ASSERT(!m_currentOperation.isNull());
auto *priv = QIOOperationPrivate::get(m_currentOperation.get());
@@ -457,7 +458,7 @@ void QRandomAccessAsyncFilePrivate::processOpen()
m_engineMutex.unlock();
QBasicMutex *mutexPtr = &m_engineMutex;
auto op = [engine = m_engine.get(), mutexPtr, mode = m_openMode] {
- QRandomAccessAsyncFilePrivate::OperationResult result{0, QIOOperation::Error::None};
+ QRandomAccessAsyncFileThreadPoolBackend::OperationResult result{0, QIOOperation::Error::None};
QMutexLocker locker(mutexPtr);
const bool res =
engine && engine->open(mode | QIODeviceBase::Unbuffered, std::nullopt);
@@ -468,13 +469,13 @@ void QRandomAccessAsyncFilePrivate::processOpen()
f = QtFuture::makeReadyVoidFuture().then(asyncFileThreadPool(), op);
} else {
f = QtFuture::makeReadyVoidFuture().then(asyncFileThreadPool(), [] {
- return QRandomAccessAsyncFilePrivate::OperationResult{0, QIOOperation::Error::Open};
+ return QRandomAccessAsyncFileThreadPoolBackend::OperationResult{0, QIOOperation::Error::Open};
});
}
m_watcher.setFuture(f);
}
-void QRandomAccessAsyncFilePrivate::operationComplete()
+void QRandomAccessAsyncFileThreadPoolBackend::operationComplete()
{
// TODO: if one of the buffers was read/written with an error,
// stop processing immediately
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index ce35e8ccffe..1e647a83dc0 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -333,12 +333,12 @@ struct TCBPoint
qreal _b;
- bool operator==(const TCBPoint &other) const
+ friend bool operator==(const TCBPoint &lhs, const TCBPoint &rhs) noexcept
{
- return _point == other._point &&
- qFuzzyCompare(_t, other._t) &&
- qFuzzyCompare(_c, other._c) &&
- qFuzzyCompare(_b, other._b);
+ return qFuzzyCompare(lhs._point, rhs._point)
+ && QtPrivate::fuzzyCompare(lhs._t, rhs._t)
+ && QtPrivate::fuzzyCompare(lhs._c, rhs._c)
+ && QtPrivate::fuzzyCompare(lhs._b, rhs._b);
}
};
Q_DECLARE_TYPEINFO(TCBPoint, Q_PRIMITIVE_TYPE);
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 0905ba3e644..1b34490e358 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -330,6 +330,13 @@ QMargins QCocoaWindow::safeAreaMargins() const
// merge them.
auto screenRect = m_view.window.screen.frame;
auto screenInsets = m_view.window.screen.safeAreaInsets;
+ auto screenSafeArea = QCocoaScreen::mapFromNative(NSMakeRect(
+ NSMinX(screenRect) + screenInsets.left,
+ NSMinY(screenRect) + screenInsets.bottom, // Non-flipped
+ NSWidth(screenRect) - screenInsets.left - screenInsets.right,
+ NSHeight(screenRect) - screenInsets.top - screenInsets.bottom
+ ));
+
auto screenRelativeViewBounds = QCocoaScreen::mapFromNative(
[m_view.window convertRectToScreen:
[m_view convertRect:m_view.bounds toView:nil]]
@@ -339,20 +346,10 @@ QMargins QCocoaWindow::safeAreaMargins() const
// Note that we do not want represent the area outside of the
// screen as being outside of the safe area.
QMarginsF screenSafeAreaMargins = {
- screenInsets.left ?
- qMax(0.0f, screenInsets.left - screenRelativeViewBounds.left())
- : 0.0f,
- screenInsets.top ?
- qMax(0.0f, screenInsets.top - screenRelativeViewBounds.top())
- : 0.0f,
- screenInsets.right ?
- qMax(0.0f, screenInsets.right
- - (screenRect.size.width - screenRelativeViewBounds.right()))
- : 0.0f,
- screenInsets.bottom ?
- qMax(0.0f, screenInsets.bottom
- - (screenRect.size.height - screenRelativeViewBounds.bottom()))
- : 0.0f
+ qMin(screenSafeArea.left() - screenRelativeViewBounds.left(), screenInsets.left),
+ qMin(screenSafeArea.top() - screenRelativeViewBounds.top(), screenInsets.top),
+ qMin(screenRelativeViewBounds.right() - screenSafeArea.right(), screenInsets.right),
+ qMin(screenRelativeViewBounds.bottom() - screenSafeArea.bottom(), screenInsets.bottom)
};
return (screenSafeAreaMargins | viewSafeAreaMargins).toMargins();