mirror of https://github.com/qt/qtbase.git
Merge remote-tracking branch 'origin/5.9.3' into 5.9
Change-Id: I9add7e07ff1b6a1cf52f59dbb8319f30e114e5fc
This commit is contained in:
commit
19378fa008
|
@ -0,0 +1,144 @@
|
|||
Qt 5.9.3 is a bug-fix release. It maintains both forward and backward
|
||||
compatibility (source and binary) with Qt 5.9.0 through 5.9.2.
|
||||
|
||||
For more details, refer to the online documentation included in this
|
||||
distribution. The documentation is also available online:
|
||||
|
||||
http://doc.qt.io/qt-5/index.html
|
||||
|
||||
The Qt version 5.9 series is binary compatible with the 5.8.x series.
|
||||
Applications compiled for 5.8 will continue to run with 5.9.
|
||||
|
||||
Some of the changes listed in this file include issue tracking numbers
|
||||
corresponding to tasks in the Qt Bug Tracker:
|
||||
|
||||
https://bugreports.qt.io/
|
||||
|
||||
Each of these identifiers can be entered in the bug tracker to obtain more
|
||||
information about a particular change.
|
||||
|
||||
****************************************************************************
|
||||
* Qt 5.9.3 Changes *
|
||||
****************************************************************************
|
||||
|
||||
QtCore
|
||||
------
|
||||
|
||||
- QFileSystemWatcher:
|
||||
* [QTBUG-64171] Fixed a bug that would cause the application to crash if
|
||||
QFileSystemWatcher was created in an auxiliary thread on Windows.
|
||||
|
||||
- QStorageInfo:
|
||||
* [QTBUG-61420] Fixed decoding of volume labels containing certain
|
||||
uncommon characters on Linux.
|
||||
|
||||
- QThreadPool:
|
||||
* Improved performance with large amount of QRunnable items.
|
||||
|
||||
QtGui
|
||||
------
|
||||
|
||||
- [QTBUG-64239] Fixed memory corruption on scaled emojis.
|
||||
- [QTBUG-63846] Fixed dragging inside a modal window when a
|
||||
QShapedPixmapWindow is used.
|
||||
- [QTBUG-61777] Fixed painting of zero-length lines with scaling.
|
||||
- [QTBUG-61244] Fixed centering of some items in layouts.
|
||||
- [QTBUG-63168] Fixed a crash when reparenting QWindowContainer.
|
||||
|
||||
|
||||
QtNetwork
|
||||
---------
|
||||
|
||||
- QHostAddress:
|
||||
* [QTBUG-63764] Fixed a problem in QHostAddress not detaching in its
|
||||
setters and thus spoiling shared data.
|
||||
|
||||
- QNetworkAccessManager:
|
||||
* [QTBUG-63075] Added support for HTTP status 308.
|
||||
* [QTBUG-61300] Fixed a problem with mixing headers from different
|
||||
responses.
|
||||
* [QTBUG-63471] Fixed redirects support in HTTP/2 protocol handler.
|
||||
* [QTBUG-63313] Fixed cookies received during a redirect not being
|
||||
applied in the redirect.
|
||||
* [QTBUG-63142] Fixed HTTP method always being changed to GET when
|
||||
redirected with 307 and 308.
|
||||
|
||||
- QNetworkCookieJar:
|
||||
* Fixed cookies with a root path ("/") not matching an empty path ("").
|
||||
|
||||
QtSql
|
||||
------
|
||||
|
||||
- PostgreSQL:
|
||||
* Fixed handling of binary data for PostgreSQL 9.x and later
|
||||
* Fixed detection of PostgreSQL 9.x and later
|
||||
|
||||
- OCI:
|
||||
* [QTBUG-57765] Fixed a bug that would see some cached results returned
|
||||
when issuing a forward only query
|
||||
|
||||
QtWidgets
|
||||
---------
|
||||
|
||||
- QAction:
|
||||
* [QTBUG-62006] Ensured setData() does not emit changed() if no change
|
||||
happened.
|
||||
|
||||
- QDockWidget:
|
||||
* [QTBUG-63526] Fixed an issue in QDockWidgets where the widget would
|
||||
not resize despite showing a resize cursor.
|
||||
|
||||
- QHeaderView:
|
||||
* [QTBUG-54601] Fixed resizing when hidden sections were involved.
|
||||
* [QTBUG-64036] Ensured maximumSectionSize property is honored during
|
||||
resizeSections().
|
||||
|
||||
- QListView:
|
||||
* [QTBUG-45427] Fixed the laying out of a QListView in a grid layout
|
||||
after the dataChanged() signal is emitted.
|
||||
|
||||
- QMenuBar
|
||||
* [QTBUG-34160] Fixed a problem with adding the same QAction to more than
|
||||
one menu.
|
||||
|
||||
- QWidget
|
||||
* [QTBUG-56860] Fixed widget losing focus after showing menu second time.
|
||||
|
||||
- QWizard:
|
||||
* [QTBUG-46894] Fixed the shortcut for the Next button on Windows.
|
||||
|
||||
|
||||
Platform-specific changes
|
||||
-------------------------
|
||||
|
||||
- Cocoa:
|
||||
* optimize backingstore flush on 10-bit displays
|
||||
* [QTBUG-57076] [QTBUG-63712] Attach menu items when updating the menubar
|
||||
* [QTBUG-63444] Toggle titlebar transparency to support unified toolbar
|
||||
|
||||
- iOS:
|
||||
* [QTBUG-57428][QTBUG-63660] add support for adding mimetypes other than text
|
||||
on the clipboard
|
||||
|
||||
- Windows:
|
||||
* [QTBUG-63654] Windows font database: Remove clamping of default font size
|
||||
|
||||
- X11:
|
||||
* [QTBUG-48034] Don't misdetect certain trackballs as tablets
|
||||
* [QTBUG-62840] Fix crash on X servers with BGR888 display
|
||||
|
||||
Third-Party Code
|
||||
----------------
|
||||
|
||||
- Improved documentation about Freetype 2 licenses.
|
||||
- Updated Sqlite to fix CVE-2017-10989.
|
||||
- Updated bundled libpng to version 1.6.34.
|
||||
|
||||
Tools
|
||||
-----
|
||||
|
||||
* qmake:
|
||||
- [QTBUG-63409] Fixed a build error with MSVC when concrt.h was included
|
||||
while exceptions are disabled.
|
||||
- [QTBUG-62985] Fixed a bug that caused the accidental creation of files
|
||||
called "NUL" when using MinGW.
|
|
@ -720,184 +720,189 @@ public class QtActivityDelegate
|
|||
|
||||
Bundle extras = m_activity.getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
|
||||
&&*/ extras.containsKey("debug_ping")
|
||||
&& extras.getString("debug_ping").equals("true")) {
|
||||
try {
|
||||
final String dc = "--Added-by-androiddeployqt--/debugger.command";
|
||||
String debuggerCommand =
|
||||
new BufferedReader(new InputStreamReader(m_activity.getAssets().open(dc))).readLine();
|
||||
String packagePath =
|
||||
m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(),
|
||||
PackageManager.GET_CONFIGURATIONS).dataDir + "/";
|
||||
try {
|
||||
final String dc = "--Added-by-androiddeployqt--/debugger.command";
|
||||
String debuggerCommand =
|
||||
new BufferedReader(new InputStreamReader(m_activity.getAssets().open(dc))).readLine();
|
||||
if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
|
||||
&&*/ extras.containsKey("debug_ping")
|
||||
&& extras.getString("debug_ping").equals("true")) {
|
||||
try {
|
||||
String packagePath =
|
||||
m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(),
|
||||
PackageManager.GET_CONFIGURATIONS).dataDir + "/";
|
||||
|
||||
debugLog("extra parameters: " + extras);
|
||||
String packageName = m_activity.getPackageName();
|
||||
String pingFile = extras.getString("ping_file");
|
||||
String pongFile = extras.getString("pong_file");
|
||||
String gdbserverSocket = extras.getString("gdbserver_socket");
|
||||
String gdbserverCommand = packagePath + debuggerCommand + gdbserverSocket;
|
||||
String pingSocket = extras.getString("ping_socket");
|
||||
boolean usePing = pingFile != null;
|
||||
boolean usePong = pongFile != null;
|
||||
boolean useSocket = gdbserverSocket != null;
|
||||
boolean usePingSocket = pingSocket != null;
|
||||
int napTime = 200; // milliseconds between file accesses
|
||||
int timeOut = 30000; // ms until we give up on ping and pong
|
||||
int maxAttempts = timeOut / napTime;
|
||||
debugLog("extra parameters: " + extras);
|
||||
String packageName = m_activity.getPackageName();
|
||||
String pingFile = extras.getString("ping_file");
|
||||
String pongFile = extras.getString("pong_file");
|
||||
String gdbserverSocket = extras.getString("gdbserver_socket");
|
||||
String gdbserverCommand = packagePath + debuggerCommand + gdbserverSocket;
|
||||
String pingSocket = extras.getString("ping_socket");
|
||||
boolean usePing = pingFile != null;
|
||||
boolean usePong = pongFile != null;
|
||||
boolean useSocket = gdbserverSocket != null;
|
||||
boolean usePingSocket = pingSocket != null;
|
||||
int napTime = 200; // milliseconds between file accesses
|
||||
int timeOut = 30000; // ms until we give up on ping and pong
|
||||
int maxAttempts = timeOut / napTime;
|
||||
|
||||
if (gdbserverSocket != null) {
|
||||
debugLog("removing gdb socket " + gdbserverSocket);
|
||||
new File(gdbserverSocket).delete();
|
||||
}
|
||||
|
||||
if (usePing) {
|
||||
debugLog("removing ping file " + pingFile);
|
||||
File ping = new File(pingFile);
|
||||
if (ping.exists()) {
|
||||
if (!ping.delete())
|
||||
debugLog("ping file cannot be deleted");
|
||||
if (gdbserverSocket != null) {
|
||||
debugLog("removing gdb socket " + gdbserverSocket);
|
||||
new File(gdbserverSocket).delete();
|
||||
}
|
||||
}
|
||||
|
||||
if (usePong) {
|
||||
debugLog("removing pong file " + pongFile);
|
||||
File pong = new File(pongFile);
|
||||
if (pong.exists()) {
|
||||
if (!pong.delete())
|
||||
debugLog("pong file cannot be deleted");
|
||||
}
|
||||
}
|
||||
|
||||
debugLog("starting " + gdbserverCommand);
|
||||
m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand);
|
||||
debugLog("gdbserver started");
|
||||
|
||||
if (useSocket) {
|
||||
int i;
|
||||
for (i = 0; i < maxAttempts; ++i) {
|
||||
debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i);
|
||||
File file = new File(gdbserverSocket);
|
||||
if (file.exists()) {
|
||||
file.setReadable(true, false);
|
||||
file.setWritable(true, false);
|
||||
file.setExecutable(true, false);
|
||||
break;
|
||||
if (usePing) {
|
||||
debugLog("removing ping file " + pingFile);
|
||||
File ping = new File(pingFile);
|
||||
if (ping.exists()) {
|
||||
if (!ping.delete())
|
||||
debugLog("ping file cannot be deleted");
|
||||
}
|
||||
Thread.sleep(napTime);
|
||||
}
|
||||
|
||||
if (i == maxAttempts) {
|
||||
debugLog("time out when waiting for debug socket");
|
||||
return false;
|
||||
if (usePong) {
|
||||
debugLog("removing pong file " + pongFile);
|
||||
File pong = new File(pongFile);
|
||||
if (pong.exists()) {
|
||||
if (!pong.delete())
|
||||
debugLog("pong file cannot be deleted");
|
||||
}
|
||||
}
|
||||
|
||||
debugLog("socket ok");
|
||||
} else {
|
||||
debugLog("socket not used");
|
||||
}
|
||||
debugLog("starting " + gdbserverCommand);
|
||||
m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand);
|
||||
debugLog("gdbserver started");
|
||||
|
||||
if (usePingSocket) {
|
||||
DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket);
|
||||
Thread waitThread = new Thread(runnable);
|
||||
waitThread.start();
|
||||
if (useSocket) {
|
||||
int i;
|
||||
for (i = 0; i < maxAttempts; ++i) {
|
||||
debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i);
|
||||
File file = new File(gdbserverSocket);
|
||||
if (file.exists()) {
|
||||
file.setReadable(true, false);
|
||||
file.setWritable(true, false);
|
||||
file.setExecutable(true, false);
|
||||
break;
|
||||
}
|
||||
Thread.sleep(napTime);
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) {
|
||||
debugLog("Waiting for debug socket connect");
|
||||
debugLog("go to sleep");
|
||||
Thread.sleep(napTime);
|
||||
}
|
||||
if (i == maxAttempts) {
|
||||
debugLog("time out when waiting for debug socket");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i == maxAttempts) {
|
||||
debugLog("time out when waiting for ping socket");
|
||||
runnable.shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (runnable.wasFailure) {
|
||||
debugLog("Could not connect to debug client");
|
||||
return false;
|
||||
debugLog("socket ok");
|
||||
} else {
|
||||
debugLog("Got pid acknowledgment");
|
||||
debugLog("socket not used");
|
||||
}
|
||||
}
|
||||
|
||||
if (usePing) {
|
||||
// Tell we are ready.
|
||||
debugLog("writing ping at " + pingFile);
|
||||
FileWriter writer = new FileWriter(pingFile);
|
||||
writer.write("" + android.os.Process.myPid());
|
||||
writer.close();
|
||||
File file = new File(pingFile);
|
||||
file.setReadable(true, false);
|
||||
file.setWritable(true, false);
|
||||
file.setExecutable(true, false);
|
||||
debugLog("wrote ping");
|
||||
} else {
|
||||
debugLog("ping not requested");
|
||||
}
|
||||
if (usePingSocket) {
|
||||
DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket);
|
||||
Thread waitThread = new Thread(runnable);
|
||||
waitThread.start();
|
||||
|
||||
// Wait until other side is ready.
|
||||
if (usePong) {
|
||||
int i;
|
||||
for (i = 0; i < maxAttempts; ++i) {
|
||||
debugLog("waiting for pong at " + pongFile + ", attempt " + i);
|
||||
File file = new File(pongFile);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
break;
|
||||
int i;
|
||||
for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) {
|
||||
debugLog("Waiting for debug socket connect");
|
||||
debugLog("go to sleep");
|
||||
Thread.sleep(napTime);
|
||||
}
|
||||
debugLog("go to sleep");
|
||||
Thread.sleep(napTime);
|
||||
}
|
||||
debugLog("Removing pingFile " + pingFile);
|
||||
new File(pingFile).delete();
|
||||
|
||||
if (i == maxAttempts) {
|
||||
debugLog("time out when waiting for pong file");
|
||||
return false;
|
||||
if (i == maxAttempts) {
|
||||
debugLog("time out when waiting for ping socket");
|
||||
runnable.shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (runnable.wasFailure) {
|
||||
debugLog("Could not connect to debug client");
|
||||
return false;
|
||||
} else {
|
||||
debugLog("Got pid acknowledgment");
|
||||
}
|
||||
}
|
||||
|
||||
debugLog("got pong " + pongFile);
|
||||
} else {
|
||||
debugLog("pong not requested");
|
||||
if (usePing) {
|
||||
// Tell we are ready.
|
||||
debugLog("writing ping at " + pingFile);
|
||||
FileWriter writer = new FileWriter(pingFile);
|
||||
writer.write("" + android.os.Process.myPid());
|
||||
writer.close();
|
||||
File file = new File(pingFile);
|
||||
file.setReadable(true, false);
|
||||
file.setWritable(true, false);
|
||||
file.setExecutable(true, false);
|
||||
debugLog("wrote ping");
|
||||
} else {
|
||||
debugLog("ping not requested");
|
||||
}
|
||||
|
||||
// Wait until other side is ready.
|
||||
if (usePong) {
|
||||
int i;
|
||||
for (i = 0; i < maxAttempts; ++i) {
|
||||
debugLog("waiting for pong at " + pongFile + ", attempt " + i);
|
||||
File file = new File(pongFile);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
break;
|
||||
}
|
||||
debugLog("go to sleep");
|
||||
Thread.sleep(napTime);
|
||||
}
|
||||
debugLog("Removing pingFile " + pingFile);
|
||||
new File(pingFile).delete();
|
||||
|
||||
if (i == maxAttempts) {
|
||||
debugLog("time out when waiting for pong file");
|
||||
return false;
|
||||
}
|
||||
|
||||
debugLog("got pong " + pongFile);
|
||||
} else {
|
||||
debugLog("pong not requested");
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} catch (SecurityException se) {
|
||||
se.printStackTrace();
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} catch (SecurityException se) {
|
||||
se.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
|
||||
&&*/ extras.containsKey("qml_debug")
|
||||
&& extras.getString("qml_debug").equals("true")) {
|
||||
String qmljsdebugger;
|
||||
if (extras.containsKey("qmljsdebugger")) {
|
||||
qmljsdebugger = extras.getString("qmljsdebugger");
|
||||
qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security
|
||||
} else {
|
||||
qmljsdebugger = "port:3768";
|
||||
if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
|
||||
&&*/ extras.containsKey("qml_debug")
|
||||
&& extras.getString("qml_debug").equals("true")) {
|
||||
String qmljsdebugger;
|
||||
if (extras.containsKey("qmljsdebugger")) {
|
||||
qmljsdebugger = extras.getString("qmljsdebugger");
|
||||
qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security
|
||||
} else {
|
||||
qmljsdebugger = "port:3768";
|
||||
}
|
||||
m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger;
|
||||
}
|
||||
m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger;
|
||||
}
|
||||
|
||||
if (extras.containsKey("extraenvvars")) {
|
||||
try {
|
||||
m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (extras.containsKey("extraenvvars")) {
|
||||
try {
|
||||
m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extras.containsKey("extraappparams")) {
|
||||
try {
|
||||
m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (extras.containsKey("extraappparams")) {
|
||||
try {
|
||||
m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// This is not an error, so keep it silent
|
||||
// e.printStackTrace();
|
||||
}
|
||||
} // extras != null
|
||||
|
||||
|
|
|
@ -214,13 +214,15 @@ bool QSemaphore::tryAcquire(int n)
|
|||
bool QSemaphore::tryAcquire(int n, int timeout)
|
||||
{
|
||||
Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
|
||||
if (timeout < 0)
|
||||
return tryAcquire(n);
|
||||
|
||||
// We're documented to accept any negative value as "forever"
|
||||
// but QDeadlineTimer only accepts -1.
|
||||
timeout = qMax(timeout, -1);
|
||||
|
||||
QDeadlineTimer timer(timeout);
|
||||
QMutexLocker locker(&d->mutex);
|
||||
qint64 remainingTime = timer.remainingTime();
|
||||
while (n > d->avail && remainingTime > 0) {
|
||||
while (n > d->avail && remainingTime != 0) {
|
||||
if (!d->cond.wait(locker.mutex(), remainingTime))
|
||||
return false;
|
||||
remainingTime = timer.remainingTime();
|
||||
|
|
|
@ -41,6 +41,8 @@ private slots:
|
|||
void tryAcquireWithTimeout_data();
|
||||
void tryAcquireWithTimeout();
|
||||
void tryAcquireWithTimeoutStarvation();
|
||||
void tryAcquireWithTimeoutForever_data();
|
||||
void tryAcquireWithTimeoutForever();
|
||||
void producerConsumer();
|
||||
};
|
||||
|
||||
|
@ -155,21 +157,25 @@ void tst_QSemaphore::tryAcquire()
|
|||
semaphore.release();
|
||||
QCOMPARE(semaphore.available(), 1);
|
||||
QVERIFY(!semaphore.tryAcquire(2));
|
||||
QVERIFY(!semaphore.tryAcquire(2, 0));
|
||||
QCOMPARE(semaphore.available(), 1);
|
||||
|
||||
semaphore.release();
|
||||
QCOMPARE(semaphore.available(), 2);
|
||||
QVERIFY(!semaphore.tryAcquire(3));
|
||||
QVERIFY(!semaphore.tryAcquire(3, 0));
|
||||
QCOMPARE(semaphore.available(), 2);
|
||||
|
||||
semaphore.release(10);
|
||||
QCOMPARE(semaphore.available(), 12);
|
||||
QVERIFY(!semaphore.tryAcquire(100));
|
||||
QVERIFY(!semaphore.tryAcquire(100, 0));
|
||||
QCOMPARE(semaphore.available(), 12);
|
||||
|
||||
semaphore.release(10);
|
||||
QCOMPARE(semaphore.available(), 22);
|
||||
QVERIFY(!semaphore.tryAcquire(100));
|
||||
QVERIFY(!semaphore.tryAcquire(100, 0));
|
||||
QCOMPARE(semaphore.available(), 22);
|
||||
|
||||
QVERIFY(semaphore.tryAcquire());
|
||||
|
@ -178,23 +184,38 @@ void tst_QSemaphore::tryAcquire()
|
|||
QVERIFY(semaphore.tryAcquire());
|
||||
QCOMPARE(semaphore.available(), 20);
|
||||
|
||||
semaphore.release(2);
|
||||
QVERIFY(semaphore.tryAcquire(1, 0));
|
||||
QCOMPARE(semaphore.available(), 21);
|
||||
|
||||
QVERIFY(semaphore.tryAcquire(1, 0));
|
||||
QCOMPARE(semaphore.available(), 20);
|
||||
|
||||
QVERIFY(semaphore.tryAcquire(10));
|
||||
QCOMPARE(semaphore.available(), 10);
|
||||
|
||||
semaphore.release(10);
|
||||
QVERIFY(semaphore.tryAcquire(10, 0));
|
||||
QCOMPARE(semaphore.available(), 10);
|
||||
|
||||
QVERIFY(semaphore.tryAcquire(10));
|
||||
QCOMPARE(semaphore.available(), 0);
|
||||
|
||||
// should not be able to acquire more
|
||||
QVERIFY(!semaphore.tryAcquire());
|
||||
QVERIFY(!semaphore.tryAcquire(1, 0));
|
||||
QCOMPARE(semaphore.available(), 0);
|
||||
|
||||
QVERIFY(!semaphore.tryAcquire());
|
||||
QVERIFY(!semaphore.tryAcquire(1, 0));
|
||||
QCOMPARE(semaphore.available(), 0);
|
||||
|
||||
QVERIFY(!semaphore.tryAcquire(10));
|
||||
QVERIFY(!semaphore.tryAcquire(10, 0));
|
||||
QCOMPARE(semaphore.available(), 0);
|
||||
|
||||
QVERIFY(!semaphore.tryAcquire(10));
|
||||
QVERIFY(!semaphore.tryAcquire(10, 0));
|
||||
QCOMPARE(semaphore.available(), 0);
|
||||
}
|
||||
|
||||
|
@ -344,6 +365,48 @@ void tst_QSemaphore::tryAcquireWithTimeoutStarvation()
|
|||
QVERIFY(consumer.wait());
|
||||
}
|
||||
|
||||
void tst_QSemaphore::tryAcquireWithTimeoutForever_data()
|
||||
{
|
||||
QTest::addColumn<int>("timeout");
|
||||
QTest::newRow("-1") << -1;
|
||||
|
||||
// tryAcquire is documented to take any negative value as "forever"
|
||||
QTest::newRow("INT_MIN") << INT_MIN;
|
||||
}
|
||||
|
||||
void tst_QSemaphore::tryAcquireWithTimeoutForever()
|
||||
{
|
||||
enum { WaitTime = 1000 };
|
||||
struct Thread : public QThread {
|
||||
QSemaphore sem;
|
||||
|
||||
void run() override
|
||||
{
|
||||
QTest::qWait(WaitTime);
|
||||
sem.release(2);
|
||||
}
|
||||
};
|
||||
|
||||
QFETCH(int, timeout);
|
||||
Thread t;
|
||||
|
||||
// sanity check it works if we can immediately acquire
|
||||
t.sem.release(11);
|
||||
QVERIFY(t.sem.tryAcquire(1, timeout));
|
||||
QVERIFY(t.sem.tryAcquire(10, timeout));
|
||||
|
||||
// verify that we do wait for at least WaitTime if we can't acquire immediately
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
t.start();
|
||||
QVERIFY(t.sem.tryAcquire(1, timeout));
|
||||
QVERIFY(timer.elapsed() >= WaitTime);
|
||||
|
||||
QVERIFY(t.wait());
|
||||
|
||||
QCOMPARE(t.sem.available(), 1);
|
||||
}
|
||||
|
||||
const char alphabet[] = "ACGTH";
|
||||
const int AlphabetSize = sizeof(alphabet) - 1;
|
||||
|
||||
|
|
Loading…
Reference in New Issue