Index: /trunk/src/corelib/io/qfilesystemwatcher_os2.cpp
===================================================================
--- /trunk/src/corelib/io/qfilesystemwatcher_os2.cpp	(revision 943)
+++ /trunk/src/corelib/io/qfilesystemwatcher_os2.cpp	(revision 944)
@@ -94,6 +94,93 @@
 QT_BEGIN_NAMESPACE
 
-QOS2FileSystemWatcherEngine::QOS2FileSystemWatcherEngine()
-    : notifyPipe(NULLHANDLE), eventSem(NULLHANDLE), isRunning(false)
+class QOS2FileSysWatcherThread : public QThread
+{
+public:
+
+    static void addRef();
+    static void release();
+
+    static QStringList addPaths(QOS2FileSystemWatcherEngine *engine,
+                                const QStringList &paths,
+                                QStringList *files,
+                                QStringList *directories);
+
+    static QStringList removePaths(QOS2FileSystemWatcherEngine *engine,
+                                   const QStringList &paths,
+                                   QStringList *files,
+                                   QStringList *directories);
+
+    static void removePaths(QOS2FileSystemWatcherEngine *engine);
+
+    static bool isOk() { return instance->notifyPipe != NULLHANDLE; }
+
+private:
+
+    QOS2FileSysWatcherThread();
+    ~QOS2FileSysWatcherThread();
+
+    void run();
+
+    int refcnt;
+
+    bool finish;
+    HFILE notifyPipe;
+    HEV eventSem;
+
+    enum Type { None = 0, Dir, File };
+    struct PathInfo
+    {
+        PathInfo(QString &p, Type t, QOS2FileSystemWatcherEngine *e = 0)
+            : path(p), type(t) { if (e) engines.append(e); }
+        QString path;
+        Type type;
+        QList<QOS2FileSystemWatcherEngine *> engines;
+    };
+    QHash<QString, QList<PathInfo> > watchedPaths;
+
+    static QOS2FileSysWatcherThread *instance;
+    static QMutex mutex;
+};
+
+// static
+QOS2FileSysWatcherThread *QOS2FileSysWatcherThread::instance = 0;
+QMutex QOS2FileSysWatcherThread::mutex;
+
+// static
+void QOS2FileSysWatcherThread::addRef()
+{
+    QMutexLocker locker(&mutex);
+
+    if (instance == 0) {
+        instance = new QOS2FileSysWatcherThread();
+    }
+
+    ++instance->refcnt;
+}
+
+// static
+void QOS2FileSysWatcherThread::release()
+{
+    QMutexLocker locker(&mutex);
+
+    Q_ASSERT(instance);
+
+    if (--instance->refcnt == 0) {
+        // make sure we don't globally exist anymore before leaving the lock
+        QOS2FileSysWatcherThread *instance = QOS2FileSysWatcherThread::instance;
+        QOS2FileSysWatcherThread::instance = 0;
+        if (instance->isRunning()) {
+            // stop the thread
+            instance->finish = true;
+            locker.unlock();
+            DosPostEventSem(instance->eventSem);
+            instance->wait();
+        }
+        delete instance;
+    }
+}
+
+QOS2FileSysWatcherThread::QOS2FileSysWatcherThread()
+    : refcnt(0), finish(false), notifyPipe(NULLHANDLE), eventSem(NULLHANDLE)
 {
     ULONG dummy, retries = 3;
@@ -138,6 +225,9 @@
 }
 
-QOS2FileSystemWatcherEngine::~QOS2FileSystemWatcherEngine()
-{
+QOS2FileSysWatcherThread::~QOS2FileSysWatcherThread()
+{
+    Q_ASSERT(!refcnt);
+    Q_ASSERT(!watchedPaths.size());
+
     if (notifyPipe != NULLHANDLE) {
         DosCloseEventSem(eventSem);
@@ -146,7 +236,8 @@
 }
 
-QStringList QOS2FileSystemWatcherEngine::addPaths(const QStringList &paths,
-                                                  QStringList *files,
-                                                  QStringList *directories)
+QStringList QOS2FileSysWatcherThread::addPaths(QOS2FileSystemWatcherEngine *engine,
+                                               const QStringList &paths,
+                                               QStringList *files,
+                                               QStringList *directories)
 {
     QMutexLocker locker(&mutex);
@@ -159,4 +250,5 @@
         if (!fi.exists())
             continue;
+
         QString normalPath = fi.absoluteFilePath();
         normalPath = QDir::toNativeSeparators(QDir::cleanPath(path)).toUpper();
@@ -171,10 +263,15 @@
                 files->append(path);
         }
-        QList<PathInfo> &variants = watchedPaths[normalPath];
+
+        QList<PathInfo> &variants = instance->watchedPaths[normalPath];
         bool alreadyAdded = false;
-        foreach (const PathInfo &pi, variants) {
-            if (pi.path == path) {
-                alreadyAdded = true;
-                break;
+        for (QList<PathInfo>::iterator pathIt = variants.begin();
+             pathIt != variants.end(); ++pathIt) {
+            if (pathIt->path == path) {
+                if (pathIt->engines.contains(engine)) {
+                    alreadyAdded = true;
+                    break;
+                }
+                pathIt->engines.append(engine);
             }
         }
@@ -182,12 +279,12 @@
             continue;
 
-        variants << PathInfo(path, type);
+        variants << PathInfo(path, type, engine);
         it.remove();
     }
 
-    if (!isRunning) {
+    if (!instance->isRunning()) {
         // (re)start the watcher thread
-        isRunning = true;
-        start(IdlePriority);
+        instance->finish = false;
+        instance->start(IdlePriority);
     }
 
@@ -195,7 +292,8 @@
 }
 
-QStringList QOS2FileSystemWatcherEngine::removePaths(const QStringList &paths,
-                                                     QStringList *files,
-                                                     QStringList *directories)
+QStringList QOS2FileSysWatcherThread::removePaths(QOS2FileSystemWatcherEngine *engine,
+                                                  const QStringList &paths,
+                                                  QStringList *files,
+                                                  QStringList *directories)
 {
     QMutexLocker locker(&mutex);
@@ -207,25 +305,30 @@
         QString normalPath = QDir::current().absoluteFilePath(path);
         normalPath = QDir::toNativeSeparators(QDir::cleanPath(path)).toUpper();
-        if (watchedPaths.contains(normalPath)) {
-            QList<PathInfo> &variants = watchedPaths[normalPath];
+
+        if (instance->watchedPaths.contains(normalPath)) {
+            QList<PathInfo> &variants = instance->watchedPaths[normalPath];
+
             for (QList<PathInfo>::iterator pathIt = variants.begin();
                  pathIt != variants.end(); ++pathIt) {
-                if (pathIt->path == path) {
+                if (pathIt->path == path && pathIt->engines.contains(engine)) {
                     files->removeAll(path);
                     directories->removeAll(path);
-                    variants.erase(pathIt);
+                    pathIt->engines.removeAll(engine);
+                    if (pathIt->engines.isEmpty())
+                        variants.erase(pathIt);
                     it.remove();
                     break;
                 }
             }
+
             if (variants.isEmpty())
-                watchedPaths.remove(normalPath);
-        }
-    }
-
-    if (watchedPaths.isEmpty()) {
+                instance->watchedPaths.remove(normalPath);
+        }
+    }
+
+    if (instance->watchedPaths.isEmpty()) {
         // stop the thread
-        isRunning = false;
-        DosPostEventSem(eventSem);
+        instance->finish = true;
+        DosPostEventSem(instance->eventSem);
     }
 
@@ -233,5 +336,32 @@
 }
 
-void QOS2FileSystemWatcherEngine::run()
+void QOS2FileSysWatcherThread::removePaths(QOS2FileSystemWatcherEngine *engine)
+{
+    QMutexLocker locker(&mutex);
+
+    foreach (const QString &normalPath, instance->watchedPaths.keys()) {
+        QList<PathInfo> &variants = instance->watchedPaths[normalPath];
+        for (QList<PathInfo>::iterator pathIt = variants.begin();
+             pathIt != variants.end(); ++pathIt) {
+            if (pathIt->engines.contains(engine)) {
+                pathIt->engines.removeAll(engine);
+                if (pathIt->engines.isEmpty())
+                    variants.erase(pathIt);
+                break;
+            }
+        }
+
+        if (variants.isEmpty())
+            instance->watchedPaths.remove(normalPath);
+    }
+
+    if (instance->watchedPaths.isEmpty()) {
+        // stop the thread
+        instance->finish = true;
+        DosPostEventSem(instance->eventSem);
+    }
+}
+
+void QOS2FileSysWatcherThread::run()
 {
     QByteArray buffer(sizeof(CNINFO) + _MAX_PATH + 2, 0);
@@ -247,5 +377,5 @@
         locker.relock();
 
-        if (!isRunning)
+        if (finish)
             break;
 
@@ -299,8 +429,10 @@
                                 type = pi.type;
                             if (type == pi.type) {
-                                if (type == File)
-                                    emit fileChanged(pi.path, deleted);
-                                else
-                                    emit directoryChanged(pi.path, deleted);
+                                foreach(QOS2FileSystemWatcherEngine *e, pi.engines) {
+                                    if (type == File)
+                                        e->doFileChanged(pi.path, deleted);
+                                    else
+                                        e->doDirectoryChanged(pi.path, deleted);
+                                }
                             }
                         }
@@ -316,5 +448,6 @@
                         foreach(const PathInfo &pi, watchedPaths[normalPath]) {
                             if (pi.type == Dir)
-                                emit directoryChanged(pi.path, false);
+                                foreach(QOS2FileSystemWatcherEngine *e, pi.engines)
+                                    e->doDirectoryChanged(pi.path, false);
                         }
                     }
@@ -334,12 +467,36 @@
 }
 
+QOS2FileSystemWatcherEngine::QOS2FileSystemWatcherEngine()
+{
+    QOS2FileSysWatcherThread::addRef();
+}
+
+QOS2FileSystemWatcherEngine::~QOS2FileSystemWatcherEngine()
+{
+    QOS2FileSysWatcherThread::release();
+}
+
+QStringList QOS2FileSystemWatcherEngine::addPaths(const QStringList &paths,
+                                                  QStringList *files,
+                                                  QStringList *directories)
+{
+    return QOS2FileSysWatcherThread::addPaths(this, paths, files, directories);
+}
+
+QStringList QOS2FileSystemWatcherEngine::removePaths(const QStringList &paths,
+                                                     QStringList *files,
+                                                     QStringList *directories)
+{
+    return QOS2FileSysWatcherThread::removePaths(this, paths, files, directories);
+}
+
 void QOS2FileSystemWatcherEngine::stop()
 {
-    QMutexLocker locker(&mutex);
-    if (isRunning) {
-        isRunning = false;
-        DosPostEventSem(eventSem);
-        // note: the caller of stop() will wait() if necessary
-    }
+    QOS2FileSysWatcherThread::removePaths(this);
+}
+
+bool QOS2FileSystemWatcherEngine::isOk() const
+{
+    return QOS2FileSysWatcherThread::isOk();
 }
 
Index: /trunk/src/corelib/io/qfilesystemwatcher_os2_p.h
===================================================================
--- /trunk/src/corelib/io/qfilesystemwatcher_os2_p.h	(revision 943)
+++ /trunk/src/corelib/io/qfilesystemwatcher_os2_p.h	(revision 944)
@@ -68,5 +68,4 @@
 class QOS2FileSystemWatcherEngine : public QFileSystemWatcherEngine
 {
-    Q_OBJECT
 public:
     QOS2FileSystemWatcherEngine();
@@ -78,23 +77,13 @@
                             QStringList *directories);
 
-    void run();
     void stop();
+    bool isOk() const;
 
-    bool isOk() const { return notifyPipe != NULLHANDLE; };
-
-private:
-    mutable QMutex mutex;
-    HFILE notifyPipe;
-    HEV eventSem;
-    bool isRunning;
-
-    enum Type { None = 0, Dir, File };
-    struct PathInfo
-    {
-        PathInfo(const QString &p, Type t) : path(p), type(t) {}
-        QString path;
-        Type type;
-    };
-    QHash<QString, QList<PathInfo> > watchedPaths;
+    void doFileChanged(const QString &path, bool removed) {
+        emit fileChanged(path, removed);
+    }
+    void doDirectoryChanged(const QString &path, bool removed) {
+        emit directoryChanged(path, removed);
+    }
 };
 
