forked from qt-creator/qt-creator
Utils: Start adding some asynchronous API to FilePath
Especially with the "remote" scenarios synchronous operations cannot be expected to work reasonably well. This here starts with adding asynchronous versions to some of the FilePath member functions, taking additional "Continuation" style. This is not necessarily the final syntax (sugar like .then(...) comes to mind...), but is simple enough for now for the few uses we have, and it is too early to see what will be needed in the end. Change-Id: Idf4dde1b77d04cafb81b6c024031145bdd91a762 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -738,6 +738,17 @@ QByteArray FilePath::fileContents(qint64 maxSize, qint64 offset) const
|
||||
return f.readAll();
|
||||
}
|
||||
|
||||
void FilePath::asyncFileContents(const Continuation<const QByteArray &> &cont,
|
||||
qint64 maxSize, qint64 offset) const
|
||||
{
|
||||
if (needsDevice()) {
|
||||
QTC_ASSERT(s_deviceHooks.asyncFileContents, return);
|
||||
return s_deviceHooks.asyncFileContents(cont, *this, maxSize, offset);
|
||||
}
|
||||
|
||||
cont(fileContents(maxSize, offset));
|
||||
}
|
||||
|
||||
bool FilePath::writeFileContents(const QByteArray &data) const
|
||||
{
|
||||
if (needsDevice()) {
|
||||
@@ -751,6 +762,17 @@ bool FilePath::writeFileContents(const QByteArray &data) const
|
||||
return res == data.size();
|
||||
}
|
||||
|
||||
void FilePath::asyncWriteFileContents(const Continuation<bool> &cont, const QByteArray &data) const
|
||||
{
|
||||
if (needsDevice()) {
|
||||
QTC_ASSERT(s_deviceHooks.asyncWriteFileContents, return);
|
||||
s_deviceHooks.asyncWriteFileContents(cont, *this, data);
|
||||
return;
|
||||
}
|
||||
|
||||
cont(writeFileContents(data));
|
||||
}
|
||||
|
||||
bool FilePath::needsDevice() const
|
||||
{
|
||||
return !m_scheme.isEmpty();
|
||||
@@ -1319,6 +1341,19 @@ bool FilePath::copyFile(const FilePath &target) const
|
||||
return QFile::copy(path(), target.path());
|
||||
}
|
||||
|
||||
void FilePath::asyncCopyFile(const std::function<void(bool)> &cont, const FilePath &target) const
|
||||
{
|
||||
if (host() != target.host()) {
|
||||
asyncFileContents([cont, target](const QByteArray &ba) {
|
||||
target.asyncWriteFileContents(cont, ba);
|
||||
});
|
||||
} else if (needsDevice()) {
|
||||
s_deviceHooks.asyncCopyFile(cont, *this, target);
|
||||
} else {
|
||||
cont(copyFile(target));
|
||||
}
|
||||
}
|
||||
|
||||
bool FilePath::renameFile(const FilePath &target) const
|
||||
{
|
||||
if (needsDevice()) {
|
||||
|
@@ -181,6 +181,13 @@ public:
|
||||
static void removeDuplicates(QList<FilePath> &files);
|
||||
static void sort(QList<FilePath> &files);
|
||||
|
||||
// Asynchronous interface
|
||||
template <class ...Args> using Continuation = std::function<void(Args...)>;
|
||||
void asyncCopyFile(const Continuation<bool> &cont, const FilePath &target) const;
|
||||
void asyncFileContents(const Continuation<const QByteArray &> &cont,
|
||||
qint64 maxSize = -1, qint64 offset = 0) const;
|
||||
void asyncWriteFileContents(const Continuation<bool> &cont, const QByteArray &data) const;
|
||||
|
||||
private:
|
||||
friend class ::tst_fileutils;
|
||||
static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath);
|
||||
|
@@ -88,6 +88,11 @@ public:
|
||||
std::function<OsType(const FilePath &)> osType;
|
||||
std::function<Environment(const FilePath &)> environment;
|
||||
std::function<qint64(const FilePath &)> fileSize;
|
||||
|
||||
template <class ...Args> using Continuation = std::function<void(Args...)>;
|
||||
std::function<void(const Continuation<bool> &, const FilePath &, const FilePath &)> asyncCopyFile;
|
||||
std::function<void(const Continuation<const QByteArray &> &, const FilePath &, qint64, qint64)> asyncFileContents;
|
||||
std::function<void(const Continuation<bool> &, const FilePath &, const QByteArray &)> asyncWriteFileContents;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT FileUtils
|
||||
|
@@ -58,6 +58,8 @@ const char DeviceManagerKey[] = "DeviceManager";
|
||||
const char DeviceListKey[] = "DeviceList";
|
||||
const char DefaultDevicesKey[] = "DefaultDevices";
|
||||
|
||||
template <class ...Args> using Continuation = std::function<void(Args...)>;
|
||||
|
||||
class DeviceManagerPrivate
|
||||
{
|
||||
public:
|
||||
@@ -495,6 +497,13 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
|
||||
return device->fileContents(filePath, maxSize, offset);
|
||||
};
|
||||
|
||||
deviceHooks.asyncFileContents = [](const Continuation<QByteArray> &cont, const FilePath &filePath,
|
||||
qint64 maxSize, qint64 offset) {
|
||||
auto device = DeviceManager::deviceForPath(filePath);
|
||||
QTC_ASSERT(device, return);
|
||||
device->asyncFileContents(cont, filePath, maxSize, offset);
|
||||
};
|
||||
|
||||
deviceHooks.writeFileContents = [](const FilePath &filePath, const QByteArray &data) {
|
||||
auto device = DeviceManager::deviceForPath(filePath);
|
||||
QTC_ASSERT(device, return false);
|
||||
|
@@ -376,6 +376,13 @@ QByteArray IDevice::fileContents(const FilePath &filePath, qint64 limit, qint64
|
||||
return {};
|
||||
}
|
||||
|
||||
void IDevice::asyncFileContents(const Continuation<QByteArray> &cont,
|
||||
const FilePath &filePath,
|
||||
qint64 limit, qint64 offset) const
|
||||
{
|
||||
cont(fileContents(filePath, limit, offset));
|
||||
}
|
||||
|
||||
bool IDevice::writeFileContents(const FilePath &filePath, const QByteArray &data) const
|
||||
{
|
||||
Q_UNUSED(filePath);
|
||||
@@ -384,6 +391,13 @@ bool IDevice::writeFileContents(const FilePath &filePath, const QByteArray &data
|
||||
return {};
|
||||
}
|
||||
|
||||
void IDevice::asyncWriteFileContents(const Continuation<bool> &cont,
|
||||
const FilePath &filePath,
|
||||
const QByteArray &data) const
|
||||
{
|
||||
cont(writeFileContents(filePath, data));
|
||||
}
|
||||
|
||||
QDateTime IDevice::lastModified(const FilePath &filePath) const
|
||||
{
|
||||
Q_UNUSED(filePath);
|
||||
|
@@ -127,6 +127,7 @@ class PROJECTEXPLORER_EXPORT IDevice : public QEnableSharedFromThis<IDevice>
|
||||
public:
|
||||
using Ptr = QSharedPointer<IDevice>;
|
||||
using ConstPtr = QSharedPointer<const IDevice>;
|
||||
template <class ...Args> using Continuation = std::function<void(Args...)>;
|
||||
|
||||
enum Origin { ManuallyAdded, AutoDetected };
|
||||
enum MachineType { Hardware, Emulator };
|
||||
@@ -272,6 +273,13 @@ public:
|
||||
|
||||
virtual void aboutToBeRemoved() const {}
|
||||
|
||||
virtual void asyncFileContents(const Continuation<QByteArray> &cont,
|
||||
const Utils::FilePath &filePath,
|
||||
qint64 limit, qint64 offset) const;
|
||||
virtual void asyncWriteFileContents(const Continuation<bool> &cont,
|
||||
const Utils::FilePath &filePath,
|
||||
const QByteArray &data) const;
|
||||
|
||||
protected:
|
||||
IDevice();
|
||||
|
||||
|
@@ -223,10 +223,11 @@ void CallgrindController::getLocalDataFile()
|
||||
// this, &CallgrindController::sftpInitialized);
|
||||
// m_sftp->start();
|
||||
|
||||
const bool res = m_valgrindOutputFile.copyFile(m_hostOutputFile);
|
||||
QTC_CHECK(res);
|
||||
|
||||
emit localParseDataAvailable(m_hostOutputFile);
|
||||
const auto afterCopy = [this](bool res) {
|
||||
QTC_CHECK(res);
|
||||
emit localParseDataAvailable(m_hostOutputFile);
|
||||
};
|
||||
m_valgrindOutputFile.asyncCopyFile(afterCopy, m_hostOutputFile);
|
||||
}
|
||||
|
||||
void CallgrindController::sftpInitialized()
|
||||
|
Reference in New Issue
Block a user