Add QFileDevice::MemoryMapFlags::MapPrivateOption flag.
Passing this flag to QFileDevice::map() will allow writes to the mapped memory without modifying the file that was mapped. These writes will be lost when the memory is unmapped. Change-Id: I7d46b044fc370585de8c06fdb4059f1f1be12d7d Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>bb10
parent
f713bd3e19
commit
3905c6f00d
|
|
@ -680,6 +680,13 @@ bool QFileDevice::setPermissions(Permissions permissions)
|
|||
function.
|
||||
|
||||
\value NoOptions No options.
|
||||
\value MapPrivateOption The mapped memory will be private, so any
|
||||
modifications will not be visible to other processes and will not
|
||||
be written to disk. Any such modifications will be lost when the
|
||||
memory is unmapped. It is unspecified whether modifications made
|
||||
to the file made after the mapping is created will be visible through
|
||||
the mapped memory. This flag is not supported on Windows CE.
|
||||
This enum value was introduced in Qt 5.4.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
|
@ -689,6 +696,10 @@ bool QFileDevice::setPermissions(Permissions permissions)
|
|||
or a new file is opened with this object, any maps that have not been
|
||||
unmapped will automatically be unmapped.
|
||||
|
||||
The mapping will have the same open mode as the file (read and/or write),
|
||||
except when using MapPrivateOption, in which case it is always possible
|
||||
to write to the mapped memory.
|
||||
|
||||
Any mapping options can be passed through \a flags.
|
||||
|
||||
Returns a pointer to the memory or 0 if there is an error.
|
||||
|
|
|
|||
|
|
@ -112,8 +112,10 @@ public:
|
|||
virtual Permissions permissions() const;
|
||||
virtual bool setPermissions(Permissions permissionSpec);
|
||||
|
||||
// ### Qt 6: rename to MemoryMapFlag & make it a QFlags
|
||||
enum MemoryMapFlags {
|
||||
NoOptions = 0
|
||||
NoOptions = 0,
|
||||
MapPrivateOption = 0x0001
|
||||
};
|
||||
|
||||
uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
|
||||
|
|
|
|||
|
|
@ -713,6 +713,12 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
|
|||
if (openMode & QIODevice::ReadOnly) access |= PROT_READ;
|
||||
if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE;
|
||||
|
||||
int sharemode = MAP_SHARED;
|
||||
if (flags & QFileDevice::MapPrivateOption) {
|
||||
sharemode = MAP_PRIVATE;
|
||||
access |= PROT_WRITE;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_INTEGRITY)
|
||||
int pageSize = sysconf(_SC_PAGESIZE);
|
||||
#else
|
||||
|
|
@ -730,7 +736,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
|
|||
realOffset &= ~(QT_OFF_T(pageSize - 1));
|
||||
|
||||
void *mapAddress = QT_MMAP((void*)0, realSize,
|
||||
access, MAP_SHARED, nativeHandle(), realOffset);
|
||||
access, sharemode, nativeHandle(), realOffset);
|
||||
if (MAP_FAILED != mapAddress) {
|
||||
uchar *address = extra + static_cast<uchar*>(mapAddress);
|
||||
maps[address] = QPair<int,size_t>(extra, realSize);
|
||||
|
|
|
|||
|
|
@ -965,6 +965,21 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
// check/setup args to map
|
||||
DWORD access = 0;
|
||||
if (flags & QFileDevice::MapPrivateOption) {
|
||||
#ifdef FILE_MAP_COPY
|
||||
access = FILE_MAP_COPY;
|
||||
#else
|
||||
q->setError(QFile::UnspecifiedError, "MapPrivateOption unsupported");
|
||||
return 0;
|
||||
#endif
|
||||
} else if (openMode & QIODevice::WriteOnly) {
|
||||
access = FILE_MAP_WRITE;
|
||||
} else if (openMode & QIODevice::ReadOnly) {
|
||||
access = FILE_MAP_READ;
|
||||
}
|
||||
|
||||
if (mapHandle == NULL) {
|
||||
// get handle to the file
|
||||
HANDLE handle = fileHandle;
|
||||
|
|
@ -1011,11 +1026,6 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
|
|||
}
|
||||
}
|
||||
|
||||
// setup args to map
|
||||
DWORD access = 0;
|
||||
if (openMode & QIODevice::ReadOnly) access = FILE_MAP_READ;
|
||||
if (openMode & QIODevice::WriteOnly) access = FILE_MAP_WRITE;
|
||||
|
||||
DWORD offsetHi = offset >> 32;
|
||||
DWORD offsetLo = offset & Q_UINT64_C(0xffffffff);
|
||||
SYSTEM_INFO sysinfo;
|
||||
|
|
|
|||
|
|
@ -3028,17 +3028,21 @@ void tst_QFile::mapResource()
|
|||
void tst_QFile::mapOpenMode_data()
|
||||
{
|
||||
QTest::addColumn<int>("openMode");
|
||||
QTest::addColumn<int>("flags");
|
||||
|
||||
QTest::newRow("ReadOnly") << int(QIODevice::ReadOnly);
|
||||
QTest::newRow("ReadOnly") << int(QIODevice::ReadOnly) << int(QFileDevice::NoOptions);
|
||||
//QTest::newRow("WriteOnly") << int(QIODevice::WriteOnly); // this doesn't make sense
|
||||
QTest::newRow("ReadWrite") << int(QIODevice::ReadWrite);
|
||||
QTest::newRow("ReadOnly,Unbuffered") << int(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
||||
QTest::newRow("ReadWrite,Unbuffered") << int(QIODevice::ReadWrite | QIODevice::Unbuffered);
|
||||
QTest::newRow("ReadWrite") << int(QIODevice::ReadWrite) << int(QFileDevice::NoOptions);
|
||||
QTest::newRow("ReadOnly,Unbuffered") << int(QIODevice::ReadOnly | QIODevice::Unbuffered) << int(QFileDevice::NoOptions);
|
||||
QTest::newRow("ReadWrite,Unbuffered") << int(QIODevice::ReadWrite | QIODevice::Unbuffered) << int(QFileDevice::NoOptions);
|
||||
QTest::newRow("ReadOnly + MapPrivate") << int(QIODevice::ReadOnly) << int(QFileDevice::MapPrivateOption);
|
||||
QTest::newRow("ReadWrite + MapPrivate") << int(QIODevice::ReadWrite) << int(QFileDevice::MapPrivateOption);
|
||||
}
|
||||
|
||||
void tst_QFile::mapOpenMode()
|
||||
{
|
||||
QFETCH(int, openMode);
|
||||
QFETCH(int, flags);
|
||||
static const qint64 fileSize = 4096;
|
||||
|
||||
QByteArray pattern(fileSize, 'A');
|
||||
|
|
@ -3060,11 +3064,15 @@ void tst_QFile::mapOpenMode()
|
|||
// open according to our mode
|
||||
QVERIFY(file.open(QIODevice::OpenMode(openMode)));
|
||||
|
||||
uchar *memory = file.map(0, fileSize);
|
||||
uchar *memory = file.map(0, fileSize, QFileDevice::MemoryMapFlags(flags));
|
||||
#if defined(Q_OS_WINCE)
|
||||
QEXPECT_FAIL("ReadOnly + MapPrivate" , "Windows CE does not support MapPrivateOption.", Abort);
|
||||
QEXPECT_FAIL("ReadWrite + MapPrivate", "Windows CE does not support MapPrivateOption.", Abort);
|
||||
#endif
|
||||
QVERIFY(memory);
|
||||
QVERIFY(memcmp(memory, pattern, fileSize) == 0);
|
||||
|
||||
if (openMode & QIODevice::WriteOnly) {
|
||||
if ((openMode & QIODevice::WriteOnly) || (flags & QFileDevice::MapPrivateOption)) {
|
||||
// try to write to the file
|
||||
*memory = 'a';
|
||||
file.unmap(memory);
|
||||
|
|
@ -3073,7 +3081,7 @@ void tst_QFile::mapOpenMode()
|
|||
file.seek(0);
|
||||
char c;
|
||||
QVERIFY(file.getChar(&c));
|
||||
QCOMPARE(c, 'a');
|
||||
QCOMPARE(c, (flags & QFileDevice::MapPrivateOption) ? 'A' : 'a');
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
|
|
|||
Loading…
Reference in New Issue