summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorSergio Ahumada <sergio.ahumada@digia.com>2013-09-21 17:34:59 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-21 18:39:13 +0200
commit4cebef621bb108c76f3cc8bfd0fdf77174b6499d (patch)
tree657eceb4539343312e7cd33b3644d1b1ec116ae2 /src/corelib
parent8969f57b6abef31d2e27500742dffa5498e38a46 (diff)
parenta5d34b34fbd867bd13ce94cdaf55d96576d4d14d (diff)
Merge "Merge branch 'stable' into dev" into refs/staging/dev
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/doc/src/threads.qdoc108
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp21
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify_p.h5
-rw-r--r--src/corelib/io/qprocess_unix.cpp40
-rw-r--r--src/corelib/thread/qfuture.qdoc5
-rw-r--r--src/corelib/thread/qfuturesynchronizer.qdoc2
-rw-r--r--src/corelib/thread/qfuturewatcher.cpp2
7 files changed, 58 insertions, 125 deletions
diff --git a/src/corelib/doc/src/threads.qdoc b/src/corelib/doc/src/threads.qdoc
index 9b80f0d200..c250f7466b 100644
--- a/src/corelib/doc/src/threads.qdoc
+++ b/src/corelib/doc/src/threads.qdoc
@@ -63,7 +63,6 @@
\li \l{Synchronizing Threads}
\li \l{Reentrancy and Thread-Safety}
\li \l{Threads and QObjects}
- \li \l{Concurrent Programming}
\li \l{Thread-Support in Qt Modules}
\endlist
@@ -449,7 +448,7 @@
\previouspage Reentrancy and Thread Safety
\contentspage Thread Support in Qt
- \nextpage Concurrent Programming
+ \nextpage Thread-Support in Qt Modules
QThread inherits QObject. It emits signals to indicate that the
thread started or finished executing, and provides a few slots as
@@ -646,113 +645,10 @@
*/
/*!
- \page threads-qtconcurrent.html
- \title Concurrent Programming
-
- \previouspage Threads and QObjects
- \contentspage Thread Support in Qt
- \nextpage Thread-Support in Qt Modules
-
- \target qtconcurrent intro
-
- The QtConcurrent namespace provides high-level APIs that make it
- possible to write multi-threaded programs without using low-level
- threading primitives such as mutexes, read-write locks, wait
- conditions, or semaphores. Programs written with QtConcurrent
- automatically adjust the number of threads used according to the
- number of processor cores available. This means that applications
- written today will continue to scale when deployed on multi-core
- systems in the future.
-
- QtConcurrent includes functional programming style APIs for
- parallel list processing, including a MapReduce and FilterReduce
- implementation for shared-memory (non-distributed) systems, and
- classes for managing asynchronous computations in GUI
- applications:
-
- \list
-
- \li QtConcurrent::map() applies a function to every item in a container,
- modifying the items in-place.
-
- \li QtConcurrent::mapped() is like map(), except that it returns a new
- container with the modifications.
-
- \li QtConcurrent::mappedReduced() is like mapped(), except that the
- modified results are reduced or folded into a single result.
-
- \li QtConcurrent::filter() removes all items from a container based on the
- result of a filter function.
-
- \li QtConcurrent::filtered() is like filter(), except that it returns a new
- container with the filtered results.
-
- \li QtConcurrent::filteredReduced() is like filtered(), except that the
- filtered results are reduced or folded into a single result.
-
- \li QtConcurrent::run() runs a function in another thread.
-
- \li QFuture represents the result of an asynchronous computation.
-
- \li QFutureIterator allows iterating through results available via QFuture.
-
- \li QFutureWatcher allows monitoring a QFuture using signals-and-slots.
-
- \li QFutureSynchronizer is a convenience class that automatically
- synchronizes several QFutures.
-
- \endlist
-
- Qt Concurrent supports several STL-compatible container and iterator types,
- but works best with Qt containers that have random-access iterators, such as
- QList or QVector. The map and filter functions accept both containers and begin/end iterators.
-
- STL Iterator support overview:
-
- \table
- \header
- \li Iterator Type
- \li Example classes
- \li Support status
- \row
- \li Input Iterator
- \li
- \li Not Supported
- \row
- \li Output Iterator
- \li
- \li Not Supported
- \row
- \li Forward Iterator
- \li std::slist
- \li Supported
- \row
- \li Bidirectional Iterator
- \li QLinkedList, std::list
- \li Supported
- \row
- \li Random Access Iterator
- \li QList, QVector, std::vector
- \li Supported and Recommended
- \endtable
-
- Random access iterators can be faster in cases where Qt Concurrent is iterating
- over a large number of lightweight items, since they allow skipping to any point
- in the container. In addition, using random access iterators allows Qt Concurrent
- to provide progress information trough QFuture::progressValue() and QFutureWatcher::
- progressValueChanged().
-
- The non in-place modifying functions such as mapped() and filtered() makes a
- copy of the container when called. If you are using STL containers this copy operation
- might take some time, in this case we recommend specifying the begin and end iterators
- for the container instead.
-*/
-
-/*!
\page threads-modules.html
\title Thread-Support in Qt Modules
- \previouspage Concurrent Programming
+ \previouspage Threads and QObjects
\contentspage Thread Support in Qt
\section1 Threads and the SQL Module
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index 024af79c33..c731f3d417 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -365,11 +365,11 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
// qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask;
int id = event.wd;
- QString path = idToPath.value(id);
+ QString path = getPathFromID(id);
if (path.isEmpty()) {
// perhaps a directory?
id = -id;
- path = idToPath.value(id);
+ path = getPathFromID(id);
if (path.isEmpty())
continue;
}
@@ -378,8 +378,9 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
if ((event.mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT)) != 0) {
pathToID.remove(path);
- idToPath.remove(id);
- inotify_rm_watch(inotifyFd, event.wd);
+ idToPath.remove(id, getPathFromID(id));
+ if (!idToPath.contains(id))
+ inotify_rm_watch(inotifyFd, event.wd);
if (id < 0)
emit directoryChanged(path, true);
@@ -394,6 +395,18 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
}
}
+QString QInotifyFileSystemWatcherEngine::getPathFromID(int id) const
+{
+ QHash<int, QString>::const_iterator i = idToPath.find(id);
+ while (i != idToPath.constEnd() && i.key() == id) {
+ if ((i + 1) == idToPath.constEnd() || (i + 1).key() != id) {
+ return i.value();
+ }
+ ++i;
+ }
+ return QString();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_inotify_p.h b/src/corelib/io/qfilesystemwatcher_inotify_p.h
index 959d9edc12..d02f04eed6 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify_p.h
+++ b/src/corelib/io/qfilesystemwatcher_inotify_p.h
@@ -79,10 +79,13 @@ private Q_SLOTS:
void readFromInotify();
private:
+ QString getPathFromID(int id) const;
+
+private:
QInotifyFileSystemWatcherEngine(int fd, QObject *parent);
int inotifyFd;
QHash<QString, int> pathToID;
- QHash<int, QString> idToPath;
+ QMultiHash<int, QString> idToPath;
QSocketNotifier notifier;
};
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 9868ea624a..eab3890beb 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -121,17 +121,33 @@ static const int errorBufferMax = 512;
static int qt_qprocess_deadChild_pipe[2];
static struct sigaction qt_sa_old_sigchld_handler;
-static void qt_sa_sigchld_handler(int signum)
+static void qt_sa_sigchld_sigaction(int signum, siginfo_t *info, void *context)
{
+ // *Never* use the info or contect variables in this function
+ // (except for passing them to the next signal in the chain).
+ // We cannot be sure if another library or if the application
+ // installed a signal handler for SIGCHLD without SA_SIGINFO
+ // and fails to pass the arguments to us. If they do that,
+ // these arguments contain garbage and we'd most likely crash.
+
qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1);
#if defined (QPROCESS_DEBUG)
fprintf(stderr, "*** SIGCHLD\n");
#endif
- // load it as volatile
- void (*oldAction)(int) = ((volatile struct sigaction *)&qt_sa_old_sigchld_handler)->sa_handler;
- if (oldAction && oldAction != SIG_IGN)
- oldAction(signum);
+ // load as volatile
+ volatile struct sigaction *vsa = &qt_sa_old_sigchld_handler;
+
+ if (qt_sa_old_sigchld_handler.sa_flags & SA_SIGINFO) {
+ void (*oldAction)(int, siginfo_t *, void *) = vsa->sa_sigaction;
+
+ oldAction(signum, info, context);
+ } else {
+ void (*oldAction)(int) = vsa->sa_handler;
+
+ if (oldAction && oldAction != SIG_IGN)
+ oldAction(signum);
+ }
}
static inline void add_fd(int &nfds, int fd, fd_set *fdset)
@@ -197,10 +213,16 @@ QProcessManager::QProcessManager()
// set up the SIGCHLD handler, which writes a single byte to the dead
// child pipe every time a child dies.
+
struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = qt_sa_sigchld_handler;
- action.sa_flags = SA_NOCLDSTOP;
+ // use the old handler as template, i.e., preserve the signal mask
+ // otherwise the original signal handler might be interrupted although it
+ // was marked to never be interrupted
+ ::sigaction(SIGCHLD, NULL, &action);
+ action.sa_sigaction = qt_sa_sigchld_sigaction;
+ // set the SA_SIGINFO flag such that we can use the three argument handler
+ // function
+ action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler);
processManagerInstance = this;
@@ -225,7 +247,7 @@ QProcessManager::~QProcessManager()
struct sigaction currentAction;
::sigaction(SIGCHLD, 0, &currentAction);
- if (currentAction.sa_handler == qt_sa_sigchld_handler) {
+ if (currentAction.sa_sigaction == qt_sa_sigchld_sigaction) {
::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0);
}
diff --git a/src/corelib/thread/qfuture.qdoc b/src/corelib/thread/qfuture.qdoc
index 421e683c4a..7ae3e4a87e 100644
--- a/src/corelib/thread/qfuture.qdoc
+++ b/src/corelib/thread/qfuture.qdoc
@@ -47,8 +47,7 @@
\ingroup thread
- To start a computation, use one of the APIs in the
- \l {Concurrent Programming}{Qt Concurrent} framework.
+ To start a computation, use one of the APIs in the \l {Qt Concurrent} framework.
QFuture allows threads to be synchronized against one or more results
which will be ready at a later point in time. The result can be of any type
@@ -93,7 +92,7 @@
To interact with running tasks using signals and slots, use QFutureWatcher.
- \sa QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
+ \sa QFutureWatcher, {Qt Concurrent}
*/
/*! \fn QFuture::QFuture()
diff --git a/src/corelib/thread/qfuturesynchronizer.qdoc b/src/corelib/thread/qfuturesynchronizer.qdoc
index 7ad978f61d..cc31dff46d 100644
--- a/src/corelib/thread/qfuturesynchronizer.qdoc
+++ b/src/corelib/thread/qfuturesynchronizer.qdoc
@@ -66,7 +66,7 @@
You can query the status of the cancel-on-wait feature using the
cancelOnWait() function.
- \sa QFuture, QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
+ \sa QFuture, QFutureWatcher, {Qt Concurrent}
*/
/*!
diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp
index 53a00a8212..a7f2dd9f73 100644
--- a/src/corelib/thread/qfuturewatcher.cpp
+++ b/src/corelib/thread/qfuturewatcher.cpp
@@ -98,7 +98,7 @@ QT_BEGIN_NAMESPACE
QFutureWatcher<void> as well. This is useful if only status or progress
information is needed; not the actual result data.
- \sa QFuture, {Concurrent Programming}{Qt Concurrent}
+ \sa QFuture, {Qt Concurrent}
*/
/*! \fn QFutureWatcher::QFutureWatcher(QObject *parent)