summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2016-03-21 09:02:57 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2016-03-21 09:02:57 +0100
commit6cb8121a44ee0f94f2c9fcb075d1d3c802d8c5c7 (patch)
tree25822898b71068f820d25a9e8372dfb348190ec1 /src/corelib
parent96740193e1e0f0608f67660811a44b696924ad4c (diff)
parent2e02de165115c9d67ac343ff0960ed80f9c09bc8 (diff)
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts: src/widgets/styles/qgtkstyle_p.cpp tests/auto/corelib/io/qtextstream/test/test.pro tests/auto/corelib/plugin/plugin.pro Change-Id: I512bc1b36acf3933ed2b96c00f476ee3819c1f4b
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/global/qlogging.cpp5
-rw-r--r--src/corelib/global/qtypeinfo.h4
-rw-r--r--src/corelib/io/qprocess_win.cpp6
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp22
-rw-r--r--src/corelib/io/qwindowspipereader.cpp154
-rw-r--r--src/corelib/io/qwindowspipereader_p.h32
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp239
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h70
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp10
-rw-r--r--src/corelib/kernel/qobject.h16
-rw-r--r--src/corelib/thread/qthread.cpp5
-rw-r--r--src/corelib/tools/qrect.h2
-rw-r--r--src/corelib/tools/qtimezone.cpp4
-rw-r--r--src/corelib/tools/qtimezoneprivate_win.cpp100
-rw-r--r--src/corelib/tools/tools.pri6
15 files changed, 441 insertions, 234 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 46cfe9e2b9..86aa9b9e7a 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -98,6 +98,11 @@ extern char *__progname;
#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || QT_HAS_INCLUDE(<sys/syscall.h>))
# include <sys/syscall.h>
+
+# if defined(Q_OS_ANDROID) && !defined(SYS_gettid)
+# define SYS_gettid __NR_gettid
+# endif
+
static long qt_gettid()
{
// no error handling
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 1200c3b5a5..e709050011 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -118,14 +118,14 @@ public:
*/
// apply defaults for a generic QTypeInfo<T> that didn't provide the new values
template <typename T, typename = void>
-struct QTypeInfoQuery : QTypeInfo<T>
+struct QTypeInfoQuery : public QTypeInfo<T>
{
enum { isRelocatable = !QTypeInfo<T>::isStatic };
};
// if QTypeInfo<T>::isRelocatable exists, use it
template <typename T>
-struct QTypeInfoQuery<T, typename QtPrivate::QEnableIf<QTypeInfo<T>::isRelocatable || true>::Type> : QTypeInfo<T>
+struct QTypeInfoQuery<T, typename QtPrivate::QEnableIf<QTypeInfo<T>::isRelocatable || true>::Type> : public QTypeInfo<T>
{};
/*!
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index ef787832a4..5d8b567c8c 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -684,10 +684,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
- // Check if we have any data pending: the pipe writer has
- // bytes waiting to written, or it has written data since the
- // last time we called stdinChannel.writer->waitForWrite().
- bool pendingDataInPipe = stdinChannel.writer && (stdinChannel.writer->bytesToWrite() || stdinChannel.writer->hadWritten());
+ bool pendingDataInPipe = stdinChannel.writer && stdinChannel.writer->bytesToWrite();
// If we don't have pending data, and our write buffer is
// empty, we fail.
@@ -815,7 +812,6 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite,
this, &QProcessPrivate::_q_canWrite);
- stdinChannel.writer->start();
}
return stdinChannel.writer->write(data, maxlen);
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index 9e3cb9ab4d..9bd5a9e3b6 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -117,6 +117,7 @@ static inline void appendTestMode(QString &path)
// Map QStandardPaths::StandardLocation to CLSID of SHGetSpecialFolderPath()
static int writableSpecialFolderClsid(QStandardPaths::StandardLocation type)
{
+#ifndef Q_OS_WINCE
static const int clsids[] = {
CSIDL_DESKTOPDIRECTORY, // DesktopLocation
CSIDL_PERSONAL, // DocumentsLocation
@@ -136,6 +137,27 @@ static int writableSpecialFolderClsid(QStandardPaths::StandardLocation type)
CSIDL_APPDATA, // AppDataLocation ("Roaming" path)
CSIDL_LOCAL_APPDATA, // AppConfigLocation ("Local" path)
};
+#else // !Q_OS_WINCE
+ static const int clsids[] = {
+ CSIDL_DESKTOPDIRECTORY, // DesktopLocation
+ CSIDL_PERSONAL, // DocumentsLocation
+ CSIDL_FONTS, // FontsLocation
+ CSIDL_PROGRAMS, // ApplicationsLocation
+ CSIDL_MYMUSIC, // MusicLocation
+ CSIDL_MYVIDEO, // MoviesLocation
+ CSIDL_MYPICTURES, // PicturesLocation
+ -1, -1, // TempLocation/HomeLocation
+ CSIDL_APPDATA, // AppLocalDataLocation, AppLocalDataLocation = DataLocation
+ -1, // CacheLocation
+ CSIDL_APPDATA, // GenericDataLocation
+ -1, // RuntimeLocation
+ CSIDL_APPDATA, // ConfigLocation
+ -1, -1, // DownloadLocation/GenericCacheLocation
+ CSIDL_APPDATA, // GenericConfigLocation
+ CSIDL_APPDATA, // AppDataLocation
+ CSIDL_APPDATA, // AppConfigLocation
+ };
+#endif // Q_OS_WINCE
Q_STATIC_ASSERT(sizeof(clsids) / sizeof(clsids[0]) == size_t(QStandardPaths::AppConfigLocation + 1));
return size_t(type) < sizeof(clsids) / sizeof(clsids[0]) ? clsids[type] : -1;
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 95232385b2..15fb276be9 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -38,28 +38,40 @@
****************************************************************************/
#include "qwindowspipereader_p.h"
-#include "qwinoverlappedionotifier_p.h"
-#include <qdebug.h>
+#include "qiodevice_p.h"
#include <qelapsedtimer.h>
-#include <qeventloop.h>
QT_BEGIN_NAMESPACE
+QWindowsPipeReader::Overlapped::Overlapped(QWindowsPipeReader *reader)
+ : pipeReader(reader)
+{
+}
+
+void QWindowsPipeReader::Overlapped::clear()
+{
+ ZeroMemory(this, sizeof(OVERLAPPED));
+}
+
+
QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
: QObject(parent),
handle(INVALID_HANDLE_VALUE),
+ overlapped(this),
readBufferMaxSize(0),
actualReadBufferSize(0),
stopped(true),
readSequenceStarted(false),
+ notifiedCalled(false),
pipeBroken(false),
- readyReadEmitted(false)
+ readyReadPending(false),
+ inReadyRead(false)
{
- dataReadNotifier = new QWinOverlappedIoNotifier(this);
- connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified);
+ connect(this, &QWindowsPipeReader::_q_queueReadyRead,
+ this, &QWindowsPipeReader::emitPendingReadyRead, Qt::QueuedConnection);
}
-static bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
+bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
{
typedef BOOL (WINAPI *PtrCancelIoEx)(HANDLE, LPOVERLAPPED);
static PtrCancelIoEx ptrCancelIoEx = 0;
@@ -88,12 +100,6 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
actualReadBufferSize = 0;
handle = hPipeReadEnd;
pipeBroken = false;
- readyReadEmitted = false;
- stopped = false;
- if (hPipeReadEnd != INVALID_HANDLE_VALUE) {
- dataReadNotifier->setHandle(hPipeReadEnd);
- dataReadNotifier->setEnabled(true);
- }
}
/*!
@@ -104,19 +110,15 @@ void QWindowsPipeReader::stop()
{
stopped = true;
if (readSequenceStarted) {
- if (qt_cancelIo(handle, &overlapped)) {
- dataReadNotifier->waitForNotified(-1, &overlapped);
- } else {
+ if (!qt_cancelIo(handle, &overlapped)) {
const DWORD dwError = GetLastError();
if (dwError != ERROR_NOT_FOUND) {
qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.",
handle);
}
}
+ waitForNotification(-1);
}
- readSequenceStarted = false;
- dataReadNotifier->setEnabled(false);
- handle = INVALID_HANDLE_VALUE;
}
/*!
@@ -174,11 +176,10 @@ bool QWindowsPipeReader::canReadLine() const
\internal
Will be called whenever the read operation completes.
*/
-void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
- OVERLAPPED *notifiedOverlapped)
+void QWindowsPipeReader::notified(DWORD errorCode, DWORD numberOfBytesRead)
{
- if (&overlapped != notifiedOverlapped)
- return;
+ notifiedCalled = true;
+ readSequenceStarted = false;
switch (errorCode) {
case ERROR_SUCCESS:
@@ -202,8 +203,6 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
break;
}
- readSequenceStarted = false;
-
// After the reader was stopped, the only reason why this function can be called is the
// completion of a cancellation. No signals should be emitted, and no new read sequence should
// be started in this case.
@@ -218,13 +217,15 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
actualReadBufferSize += numberOfBytesRead;
readBuffer.truncate(actualReadBufferSize);
startAsyncRead();
- readyReadEmitted = true;
- emit readyRead();
+ if (!readyReadPending) {
+ readyReadPending = true;
+ emit _q_queueReadyRead(QWindowsPipeReader::QPrivateSignal());
+ }
}
/*!
\internal
- Reads data from the socket into the readbuffer
+ Reads data from the pipe into the readbuffer.
*/
void QWindowsPipeReader::startAsyncRead()
{
@@ -244,43 +245,41 @@ void QWindowsPipeReader::startAsyncRead()
char *ptr = readBuffer.reserve(bytesToRead);
+ stopped = false;
readSequenceStarted = true;
- ZeroMemory(&overlapped, sizeof(overlapped));
- if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
- // We get notified by the QWinOverlappedIoNotifier - even in the synchronous case.
- return;
- } else {
+ overlapped.clear();
+ if (!ReadFileEx(handle, ptr, bytesToRead, &overlapped, &readFileCompleted)) {
+ readSequenceStarted = false;
+
const DWORD dwError = GetLastError();
switch (dwError) {
- case ERROR_IO_PENDING:
- // This is not an error. We're getting notified, when data arrives.
- return;
- case ERROR_MORE_DATA:
- // This is not an error. The synchronous read succeeded.
- // We're connected to a message mode pipe and the message
- // didn't fit into the pipe's system buffer.
- // We're getting notified by the QWinOverlappedIoNotifier.
- break;
case ERROR_BROKEN_PIPE:
case ERROR_PIPE_NOT_CONNECTED:
- {
- // It may happen, that the other side closes the connection directly
- // after writing data. Then we must set the appropriate socket state.
- readSequenceStarted = false;
- pipeBroken = true;
- emit pipeClosed();
- return;
- }
+ // It may happen, that the other side closes the connection directly
+ // after writing data. Then we must set the appropriate socket state.
+ pipeBroken = true;
+ emit pipeClosed();
+ break;
default:
- readSequenceStarted = false;
emit winError(dwError, QLatin1String("QWindowsPipeReader::startAsyncRead"));
- return;
+ break;
}
}
}
/*!
\internal
+ Called when ReadFileEx finished the read operation.
+ */
+void QWindowsPipeReader::readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase)
+{
+ Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase);
+ overlapped->pipeReader->notified(errorCode, numberOfBytesTransfered);
+}
+
+/*!
+ \internal
Returns the number of available bytes in the pipe.
Sets QWindowsPipeReader::pipeBroken to true if the connection is broken.
*/
@@ -298,17 +297,60 @@ DWORD QWindowsPipeReader::checkPipeState()
return 0;
}
+bool QWindowsPipeReader::waitForNotification(int timeout)
+{
+ QElapsedTimer t;
+ t.start();
+ notifiedCalled = false;
+ int msecs = timeout;
+ while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
+ if (notifiedCalled)
+ return true;
+
+ // Some other I/O completion routine was called. Wait some more.
+ msecs = qt_subtract_from_timeout(timeout, t.elapsed());
+ if (!msecs)
+ break;
+ }
+ return notifiedCalled;
+}
+
+void QWindowsPipeReader::emitPendingReadyRead()
+{
+ if (readyReadPending) {
+ readyReadPending = false;
+ inReadyRead = true;
+ emit readyRead();
+ inReadyRead = false;
+ }
+}
+
/*!
Waits for the completion of the asynchronous read operation.
- Returns \c true, if we've emitted the readyRead signal.
+ Returns \c true, if we've emitted the readyRead signal (non-recursive case)
+ or readyRead will be emitted by the event loop (recursive case).
*/
bool QWindowsPipeReader::waitForReadyRead(int msecs)
{
if (!readSequenceStarted)
return false;
- readyReadEmitted = false;
- dataReadNotifier->waitForNotified(msecs, &overlapped);
- return readyReadEmitted;
+
+ if (readyReadPending) {
+ if (!inReadyRead)
+ emitPendingReadyRead();
+ return true;
+ }
+
+ if (!waitForNotification(msecs))
+ return false;
+
+ if (readyReadPending) {
+ if (!inReadyRead)
+ emitPendingReadyRead();
+ return true;
+ }
+
+ return false;
}
/*!
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index d389d0cc9f..74ff5250ac 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -51,7 +51,6 @@
// We mean it.
//
-#include <qbytearray.h>
#include <qobject.h>
#include <private/qringbuffer_p.h>
@@ -59,9 +58,6 @@
QT_BEGIN_NAMESPACE
-
-class QWinOverlappedIoNotifier;
-
class Q_CORE_EXPORT QWindowsPipeReader : public QObject
{
Q_OBJECT
@@ -70,6 +66,7 @@ public:
~QWindowsPipeReader();
void setHandle(HANDLE hPipeReadEnd);
+ void startAsyncRead();
void stop();
void setMaxReadBufferSize(qint64 size) { readBufferMaxSize = size; }
@@ -82,31 +79,42 @@ public:
bool waitForReadyRead(int msecs);
bool waitForPipeClosed(int msecs);
- void startAsyncRead();
bool isReadOperationActive() const { return readSequenceStarted; }
Q_SIGNALS:
void winError(ulong, const QString &);
void readyRead();
void pipeClosed();
-
-private Q_SLOTS:
- void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped);
+ void _q_queueReadyRead(QPrivateSignal);
private:
+ static void CALLBACK readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase);
+ void notified(DWORD errorCode, DWORD numberOfBytesRead);
DWORD checkPipeState();
+ bool waitForNotification(int timeout);
+ void emitPendingReadyRead();
+
+ class Overlapped : public OVERLAPPED
+ {
+ Q_DISABLE_COPY(Overlapped)
+ public:
+ explicit Overlapped(QWindowsPipeReader *reader);
+ void clear();
+ QWindowsPipeReader *pipeReader;
+ };
-private:
HANDLE handle;
- OVERLAPPED overlapped;
- QWinOverlappedIoNotifier *dataReadNotifier;
+ Overlapped overlapped;
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
qint64 actualReadBufferSize;
bool stopped;
bool readSequenceStarted;
+ bool notifiedCalled;
bool pipeBroken;
- bool readyReadEmitted;
+ bool readyReadPending;
+ bool inReadyRead;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index c7144d2c6b..79e7d13eb5 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -38,144 +38,177 @@
****************************************************************************/
#include "qwindowspipewriter_p.h"
+#include "qiodevice_p.h"
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_THREAD
+extern bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped); // from qwindowspipereader.cpp
-QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipe, QObject * parent)
- : QThread(parent),
- writePipe(INVALID_HANDLE_VALUE),
- quitNow(false),
- hasWritten(false)
+
+QWindowsPipeWriter::Overlapped::Overlapped(QWindowsPipeWriter *pipeWriter)
+ : pipeWriter(pipeWriter)
+{
+}
+
+void QWindowsPipeWriter::Overlapped::clear()
{
- DuplicateHandle(GetCurrentProcess(), pipe, GetCurrentProcess(),
- &writePipe, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ ZeroMemory(this, sizeof(OVERLAPPED));
+}
+
+
+QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent)
+ : QObject(parent),
+ handle(pipeWriteEnd),
+ overlapped(this),
+ numberOfBytesToWrite(0),
+ pendingBytesWrittenValue(0),
+ stopped(true),
+ writeSequenceStarted(false),
+ notifiedCalled(false),
+ bytesWrittenPending(false),
+ inBytesWritten(false)
+{
+ connect(this, &QWindowsPipeWriter::_q_queueBytesWritten,
+ this, &QWindowsPipeWriter::emitPendingBytesWrittenValue, Qt::QueuedConnection);
}
QWindowsPipeWriter::~QWindowsPipeWriter()
{
- lock.lock();
- quitNow = true;
- waitCondition.wakeOne();
- lock.unlock();
- if (!wait(30000))
- terminate();
- CloseHandle(writePipe);
+ stop();
}
bool QWindowsPipeWriter::waitForWrite(int msecs)
{
- QMutexLocker locker(&lock);
- bool hadWritten = hasWritten;
- hasWritten = false;
- if (hadWritten)
+ if (!writeSequenceStarted)
+ return false;
+
+ if (bytesWrittenPending) {
+ if (!inBytesWritten)
+ emitPendingBytesWrittenValue();
return true;
- if (!waitCondition.wait(&lock, msecs))
+ }
+
+ if (!waitForNotification(msecs))
return false;
- hadWritten = hasWritten;
- hasWritten = false;
- return hadWritten;
+
+ if (bytesWrittenPending) {
+ if (!inBytesWritten)
+ emitPendingBytesWrittenValue();
+ return true;
+ }
+
+ return false;
}
-qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
+qint64 QWindowsPipeWriter::bytesToWrite() const
{
- if (!isRunning())
- return -1;
-
- QMutexLocker locker(&lock);
- data.append(ptr, maxlen);
- waitCondition.wakeOne();
- return maxlen;
+ return numberOfBytesToWrite;
}
-class QPipeWriterOverlapped
+void QWindowsPipeWriter::emitPendingBytesWrittenValue()
{
-public:
- QPipeWriterOverlapped()
- {
- overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (bytesWrittenPending) {
+ bytesWrittenPending = false;
+ const qint64 bytes = pendingBytesWrittenValue;
+ pendingBytesWrittenValue = 0;
+
+ inBytesWritten = true;
+ emit bytesWritten(bytes);
+ inBytesWritten = false;
+ emit canWrite();
}
+}
- ~QPipeWriterOverlapped()
- {
- CloseHandle(overlapped.hEvent);
- }
+void QWindowsPipeWriter::writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase)
+{
+ Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase);
+ overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered);
+}
- void prepare()
- {
- const HANDLE hEvent = overlapped.hEvent;
- ZeroMemory(&overlapped, sizeof overlapped);
- overlapped.hEvent = hEvent;
+/*!
+ \internal
+ Will be called whenever the write operation completes.
+ */
+void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten)
+{
+ notifiedCalled = true;
+ writeSequenceStarted = false;
+ numberOfBytesToWrite = 0;
+
+ switch (errorCode) {
+ case ERROR_SUCCESS:
+ break;
+ case ERROR_OPERATION_ABORTED:
+ if (stopped)
+ break;
+ // fall through
+ default:
+ qErrnoWarning(errorCode, "QWindowsPipeWriter: asynchronous write failed.");
+ break;
}
- OVERLAPPED *operator&()
- {
- return &overlapped;
+ // After the writer was stopped, the only reason why this function can be called is the
+ // completion of a cancellation. No signals should be emitted, and no new write sequence should
+ // be started in this case.
+ if (stopped)
+ return;
+
+ pendingBytesWrittenValue += qint64(numberOfBytesWritten);
+ if (!bytesWrittenPending) {
+ bytesWrittenPending = true;
+ emit _q_queueBytesWritten(QWindowsPipeWriter::QPrivateSignal());
}
+}
-private:
- OVERLAPPED overlapped;
-};
+bool QWindowsPipeWriter::waitForNotification(int timeout)
+{
+ QElapsedTimer t;
+ t.start();
+ notifiedCalled = false;
+ int msecs = timeout;
+ while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
+ if (notifiedCalled)
+ return true;
+
+ // Some other I/O completion routine was called. Wait some more.
+ msecs = qt_subtract_from_timeout(timeout, t.elapsed());
+ if (!msecs)
+ break;
+ }
+ return notifiedCalled;
+}
-void QWindowsPipeWriter::run()
+qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
{
- QPipeWriterOverlapped overl;
- forever {
- lock.lock();
- while(data.isEmpty() && (!quitNow)) {
- waitCondition.wakeOne();
- waitCondition.wait(&lock);
- }
+ if (writeSequenceStarted)
+ return 0;
+
+ overlapped.clear();
+ numberOfBytesToWrite = maxlen;
+ stopped = false;
+ writeSequenceStarted = true;
+ if (!WriteFileEx(handle, ptr, maxlen, &overlapped, &writeFileCompleted)) {
+ writeSequenceStarted = false;
+ qErrnoWarning("QWindowsPipeWriter::write failed.");
+ }
- if (quitNow) {
- lock.unlock();
- quitNow = false;
- break;
- }
+ return maxlen;
+}
- QByteArray copy = data;
-
- lock.unlock();
-
- const char *ptrData = copy.data();
- qint64 maxlen = copy.size();
- qint64 totalWritten = 0;
- overl.prepare();
- while ((!quitNow) && totalWritten < maxlen) {
- DWORD written = 0;
- if (!WriteFile(writePipe, ptrData + totalWritten,
- maxlen - totalWritten, &written, &overl)) {
- const DWORD writeError = GetLastError();
- if (writeError == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) {
- // give the os a rest
- msleep(100);
- continue;
- }
- if (writeError != ERROR_IO_PENDING) {
- qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed.");
- return;
- }
- if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) {
- qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed.");
- return;
- }
+void QWindowsPipeWriter::stop()
+{
+ stopped = true;
+ if (writeSequenceStarted) {
+ if (!qt_cancelIo(handle, &overlapped)) {
+ const DWORD dwError = GetLastError();
+ if (dwError != ERROR_NOT_FOUND) {
+ qErrnoWarning(dwError, "QWindowsPipeWriter: qt_cancelIo on handle %x failed.",
+ handle);
}
- totalWritten += written;
-#if defined QPIPEWRITER_DEBUG
- qDebug("QWindowsPipeWriter::run() wrote %d %d/%d bytes",
- written, int(totalWritten), int(maxlen));
-#endif
- lock.lock();
- data.remove(0, written);
- hasWritten = true;
- lock.unlock();
}
- emit bytesWritten(totalWritten);
- emit canWrite();
+ waitForNotification(-1);
}
}
-#endif //QT_NO_THREAD
-
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
index 49fb85ebdd..945cbd18bf 100644
--- a/src/corelib/io/qwindowspipewriter_p.h
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -52,16 +52,11 @@
//
#include <qelapsedtimer.h>
-#include <qthread.h>
-#include <qmutex.h>
-#include <qwaitcondition.h>
+#include <qobject.h>
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_THREAD
-
#define SLEEPMIN 10
#define SLEEPMAX 500
@@ -110,45 +105,50 @@ private:
int nextSleep;
};
-class Q_CORE_EXPORT QWindowsPipeWriter : public QThread
+class Q_CORE_EXPORT QWindowsPipeWriter : public QObject
{
Q_OBJECT
-
-Q_SIGNALS:
- void canWrite();
- void bytesWritten(qint64 bytes);
-
public:
- explicit QWindowsPipeWriter(HANDLE writePipe, QObject * parent = 0);
+ explicit QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent = 0);
~QWindowsPipeWriter();
- bool waitForWrite(int msecs);
qint64 write(const char *data, qint64 maxlen);
+ void stop();
+ bool waitForWrite(int msecs);
+ qint64 bytesToWrite() const;
- qint64 bytesToWrite() const
- {
- QMutexLocker locker(&lock);
- return data.size();
- }
-
- bool hadWritten() const
- {
- return hasWritten;
- }
-
-protected:
- void run();
+Q_SIGNALS:
+ void canWrite();
+ void bytesWritten(qint64 bytes);
+ void _q_queueBytesWritten(QPrivateSignal);
private:
- QByteArray data;
- QWaitCondition waitCondition;
- mutable QMutex lock;
- HANDLE writePipe;
- volatile bool quitNow;
- bool hasWritten;
-};
+ static void CALLBACK writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase);
+ void notified(DWORD errorCode, DWORD numberOfBytesWritten);
+ bool waitForNotification(int timeout);
+ void emitPendingBytesWrittenValue();
-#endif //QT_NO_THREAD
+ class Overlapped : public OVERLAPPED
+ {
+ Q_DISABLE_COPY(Overlapped)
+ public:
+ explicit Overlapped(QWindowsPipeWriter *pipeWriter);
+ void clear();
+
+ QWindowsPipeWriter *pipeWriter;
+ };
+
+ HANDLE handle;
+ Overlapped overlapped;
+ qint64 numberOfBytesToWrite;
+ qint64 pendingBytesWrittenValue;
+ bool stopped;
+ bool writeSequenceStarted;
+ bool notifiedCalled;
+ bool bytesWrittenPending;
+ bool inBytesWritten;
+};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index bef105b184..a6f61afc90 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -216,8 +216,10 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector();
if (waitTime)
emit aboutToBlock();
+ bool timerEventsSent = false;
DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, waitTime, TRUE);
- if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
+ while (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
+ timerEventsSent = true;
const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0);
ResetEvent(handle);
const int timerId = d->timerHandleToId.value(handle);
@@ -232,12 +234,10 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
// Update timer's targetTime
const quint64 targetTime = qt_msectime() + info.interval;
info.targetTime = targetTime;
- emit awake();
- return true;
+ waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 0, TRUE);
}
emit awake();
-
- if (userEventsSent)
+ if (timerEventsSent || userEventsSent)
return true;
// We cannot wait infinitely like on other platforms, as
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index a070ddd805..1f3d3dcfc7 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -119,8 +119,8 @@ public:
Q_INVOKABLE explicit QObject(QObject *parent=Q_NULLPTR);
virtual ~QObject();
- virtual bool event(QEvent *);
- virtual bool eventFilter(QObject *, QEvent *);
+ virtual bool event(QEvent *event);
+ virtual bool eventFilter(QObject *watched, QEvent *event);
#ifdef Q_QDOC
static QString tr(const char *sourceText, const char *comment = Q_NULLPTR, int n = -1);
@@ -195,9 +195,9 @@ public:
inline const QObjectList &children() const { return d_ptr->children; }
- void setParent(QObject *);
- void installEventFilter(QObject *);
- void removeEventFilter(QObject *);
+ void setParent(QObject *parent);
+ void installEventFilter(QObject *filterObj);
+ void removeEventFilter(QObject *obj);
static QMetaObject::Connection connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);
@@ -428,9 +428,9 @@ protected:
int receivers(const char* signal) const;
bool isSignalConnected(const QMetaMethod &signal) const;
- virtual void timerEvent(QTimerEvent *);
- virtual void childEvent(QChildEvent *);
- virtual void customEvent(QEvent *);
+ virtual void timerEvent(QTimerEvent *event);
+ virtual void childEvent(QChildEvent *event);
+ virtual void customEvent(QEvent *event);
virtual void connectNotify(const QMetaMethod &signal);
virtual void disconnectNotify(const QMetaMethod &signal);
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 48b94abae5..8a797772fc 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -310,8 +310,9 @@ QThreadPrivate::~QThreadPrivate()
The effect of the \a priority parameter is dependent on the
operating system's scheduling policy. In particular, the \a priority
will be ignored on systems that do not support thread priorities
- (such as on Linux, see http://linux.die.net/man/2/sched_setscheduler
- for more details).
+ (such as on Linux, see the
+ \l {http://linux.die.net/man/2/sched_setscheduler}{sched_setscheduler}
+ documentation for more details).
\sa run(), terminate()
*/
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
index 31fdc8ce6b..b376b6b999 100644
--- a/src/corelib/tools/qrect.h
+++ b/src/corelib/tools/qrect.h
@@ -252,7 +252,7 @@ Q_DECL_CONSTEXPR inline QPoint QRect::bottomLeft() const Q_DECL_NOTHROW
{ return QPoint(x1, y2); }
Q_DECL_CONSTEXPR inline QPoint QRect::center() const Q_DECL_NOTHROW
-{ return QPoint((x1+x2)/2, (y1+y2)/2); }
+{ return QPoint(int((qint64(x1)+x2)/2), int((qint64(y1)+y2)/2)); } // cast avoids overflow on addition
Q_DECL_CONSTEXPR inline int QRect::width() const Q_DECL_NOTHROW
{ return x2 - x1 + 1; }
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index 4672248945..3c7417d64e 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -67,7 +67,7 @@ static QTimeZonePrivate *newBackendTimeZone()
#elif defined Q_OS_UNIX
return new QTzTimeZonePrivate();
// Registry based timezone backend not available on WinRT
-#elif defined Q_OS_WIN && !defined Q_OS_WINRT
+#elif defined Q_OS_WIN
return new QWinTimeZonePrivate();
#elif defined QT_USE_ICU
return new QIcuTimeZonePrivate();
@@ -94,7 +94,7 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
#elif defined Q_OS_UNIX
return new QTzTimeZonePrivate(ianaId);
// Registry based timezone backend not available on WinRT
-#elif defined Q_OS_WIN && !defined Q_OS_WINRT
+#elif defined Q_OS_WIN
return new QWinTimeZonePrivate(ianaId);
#elif defined QT_USE_ICU
return new QIcuTimeZonePrivate(ianaId);
diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp
index 1d19f01b4e..f84b66fa99 100644
--- a/src/corelib/tools/qtimezoneprivate_win.cpp
+++ b/src/corelib/tools/qtimezoneprivate_win.cpp
@@ -48,6 +48,10 @@
QT_BEGIN_NAMESPACE
+#ifndef Q_OS_WINRT
+#define QT_USE_REGISTRY_TIMEZONE 1
+#endif
+
/*
Private
@@ -65,9 +69,10 @@ QT_BEGIN_NAMESPACE
// Vista introduced support for historic data, see MSDN docs on DYNAMIC_TIME_ZONE_INFORMATION
// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms724253%28v=vs.85%29.aspx
-
+#ifdef QT_USE_REGISTRY_TIMEZONE
static const char tzRegPath[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
static const char currTzRegPath[] = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
+#endif
enum {
MIN_YEAR = -292275056,
@@ -129,6 +134,7 @@ static bool equalTzi(const TIME_ZONE_INFORMATION &tzi1, const TIME_ZONE_INFORMAT
&& wcscmp(tzi1.DaylightName, tzi2.DaylightName) == 0);
}
+#ifdef QT_USE_REGISTRY_TIMEZONE
static bool openRegistryKey(const QString &keyPath, HKEY *key)
{
return (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (const wchar_t*)keyPath.utf16(), 0, KEY_READ, key)
@@ -203,9 +209,61 @@ static TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *o
return tzi;
}
+#else // QT_USE_REGISTRY_TIMEZONE
+struct QWinDynamicTimeZone
+{
+ QString standardName;
+ QString daylightName;
+ QString timezoneName;
+ qint32 bias;
+ bool daylightTime;
+};
+
+typedef QHash<QByteArray, QWinDynamicTimeZone> QWinRTTimeZoneHash;
+
+Q_GLOBAL_STATIC(QWinRTTimeZoneHash, gTimeZones)
+
+static void enumerateTimeZones()
+{
+ DYNAMIC_TIME_ZONE_INFORMATION dtzInfo;
+ quint32 index = 0;
+ QString prevTimeZoneKeyName;
+ while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) {
+ QWinDynamicTimeZone item;
+ item.timezoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName);
+ // As soon as key name repeats, break. Some systems continue to always
+ // return the last item independent of index being out of range
+ if (item.timezoneName == prevTimeZoneKeyName)
+ break;
+ item.standardName = QString::fromWCharArray(dtzInfo.StandardName);
+ item.daylightName = QString::fromWCharArray(dtzInfo.DaylightName);
+ item.daylightTime = !dtzInfo.DynamicDaylightTimeDisabled;
+ item.bias = dtzInfo.Bias;
+ gTimeZones->insert(item.timezoneName.toUtf8(), item);
+ prevTimeZoneKeyName = item.timezoneName;
+ }
+}
+
+static DYNAMIC_TIME_ZONE_INFORMATION dynamicInfoForId(const QByteArray &windowsId)
+{
+ DYNAMIC_TIME_ZONE_INFORMATION dtzInfo;
+ quint32 index = 0;
+ QString prevTimeZoneKeyName;
+ while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) {
+ const QString timeZoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName);
+ if (timeZoneName == QLatin1String(windowsId))
+ break;
+ if (timeZoneName == prevTimeZoneKeyName)
+ break;
+ prevTimeZoneKeyName = timeZoneName;
+ }
+ return dtzInfo;
+}
+#endif // QT_USE_REGISTRY_TIMEZONE
static QList<QByteArray> availableWindowsIds()
{
+#ifdef QT_USE_REGISTRY_TIMEZONE
// TODO Consider caching results in a global static, very unlikely to change.
QList<QByteArray> list;
HKEY key = NULL;
@@ -223,10 +281,16 @@ static QList<QByteArray> availableWindowsIds()
RegCloseKey(key);
}
return list;
+#else // QT_USE_REGISTRY_TIMEZONE
+ if (gTimeZones->isEmpty())
+ enumerateTimeZones();
+ return gTimeZones->keys();
+#endif // QT_USE_REGISTRY_TIMEZONE
}
static QByteArray windowsSystemZoneId()
{
+#ifdef QT_USE_REGISTRY_TIMEZONE
// On Vista and later is held in the value TimeZoneKeyName in key currTzRegPath
QString id;
HKEY key = NULL;
@@ -248,6 +312,11 @@ static QByteArray windowsSystemZoneId()
if (equalTzi(getRegistryTzi(winId, &ok), sysTzi))
return winId;
}
+#else // QT_USE_REGISTRY_TIMEZONE
+ DYNAMIC_TIME_ZONE_INFORMATION dtzi;
+ if (SUCCEEDED(GetDynamicTimeZoneInformation(&dtzi)))
+ return QString::fromWCharArray(dtzi.TimeZoneKeyName).toLocal8Bit();
+#endif // QT_USE_REGISTRY_TIMEZONE
// If we can't determine the current ID use UTC
return QTimeZonePrivate::utcQByteArray();
@@ -368,6 +437,7 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
}
if (!m_windowsId.isEmpty()) {
+#ifdef QT_USE_REGISTRY_TIMEZONE
// Open the base TZI for the time zone
HKEY baseKey = NULL;
const QString baseKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\')
@@ -404,6 +474,34 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
}
RegCloseKey(baseKey);
}
+#else // QT_USE_REGISTRY_TIMEZONE
+ if (gTimeZones->isEmpty())
+ enumerateTimeZones();
+ QWinRTTimeZoneHash::const_iterator it = gTimeZones->find(m_windowsId);
+ if (it != gTimeZones->constEnd()) {
+ m_displayName = it->timezoneName;
+ m_standardName = it->standardName;
+ m_daylightName = it->daylightName;
+ DWORD firstYear = 0;
+ DWORD lastYear = 0;
+ DYNAMIC_TIME_ZONE_INFORMATION dtzi = dynamicInfoForId(m_windowsId);
+ GetDynamicTimeZoneInformationEffectiveYears(&dtzi, &firstYear, &lastYear);
+ // If there is no dynamic information, you can still query for
+ // year 0, which helps simplifying following part
+ for (DWORD year = firstYear; year <= lastYear; ++year) {
+ TIME_ZONE_INFORMATION tzi;
+ if (!GetTimeZoneInformationForYear(year, &dtzi, &tzi))
+ continue;
+ QWinTransitionRule rule;
+ rule.standardTimeBias = tzi.Bias + tzi.StandardBias;
+ rule.daylightTimeBias = tzi.Bias + tzi.DaylightBias - rule.standardTimeBias;
+ rule.standardTimeRule = tzi.StandardDate;
+ rule.daylightTimeRule = tzi.DaylightDate;
+ rule.startYear = year;
+ m_tranRules.append(rule);
+ }
+ }
+#endif // QT_USE_REGISTRY_TIMEZONE
}
// If there are no rules then we failed to find a windowsId or any tzi info
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index e367e6e716..93dc71c3d8 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -144,9 +144,11 @@ else:unix {
SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/qtimezoneprivate_tz.cpp
}
else:win32 {
- SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp
- !winrt: SOURCES += tools/qtimezoneprivate_win.cpp
+ SOURCES += tools/qelapsedtimer_win.cpp \
+ tools/qlocale_win.cpp \
+ tools/qtimezoneprivate_win.cpp
winphone: LIBS_PRIVATE += -lWindowsPhoneGlobalizationUtil
+ winrt-*-msvc2013: LIBS += advapi32.lib
} else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp
else:SOURCES += tools/qelapsedtimer_generic.cpp