diff options
author | Sergio Ahumada <sergio.ahumada@digia.com> | 2013-09-21 17:32:39 +0200 |
---|---|---|
committer | Sergio Ahumada <sergio.ahumada@digia.com> | 2013-09-21 17:33:15 +0200 |
commit | a5d34b34fbd867bd13ce94cdaf55d96576d4d14d (patch) | |
tree | bb3b8b902f13bda65e49485a789f0eca07329ab5 /src/corelib | |
parent | 5957f245c6c77c98d7e90d614c9fe2cdbfe7e8e6 (diff) | |
parent | a23ff58d716f62b02ec825a3ea3c6b07616ee3f0 (diff) |
Merge branch 'stable' into dev
Change-Id: I37d85631ab1165ab91457d8880c4da907a9df73b
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/doc/src/threads.qdoc | 108 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_inotify.cpp | 21 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_inotify_p.h | 5 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 40 | ||||
-rw-r--r-- | src/corelib/thread/qfuture.qdoc | 5 | ||||
-rw-r--r-- | src/corelib/thread/qfuturesynchronizer.qdoc | 2 | ||||
-rw-r--r-- | src/corelib/thread/qfuturewatcher.cpp | 2 |
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, ¤tAction); - 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) |