Changeset 944


Ignore:
Timestamp:
Aug 5, 2011, 5:02:29 PM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

OS/2: Make native QFileSystemWatcher engine a singleton.

This reduces the number of clients to the system-wide server
that performs file system change notification.

Location:
trunk/src/corelib/io
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/io/qfilesystemwatcher_os2.cpp

    r943 r944  
    9494QT_BEGIN_NAMESPACE
    9595
    96 QOS2FileSystemWatcherEngine::QOS2FileSystemWatcherEngine()
    97     : notifyPipe(NULLHANDLE), eventSem(NULLHANDLE), isRunning(false)
     96class QOS2FileSysWatcherThread : public QThread
     97{
     98public:
     99
     100    static void addRef();
     101    static void release();
     102
     103    static QStringList addPaths(QOS2FileSystemWatcherEngine *engine,
     104                                const QStringList &paths,
     105                                QStringList *files,
     106                                QStringList *directories);
     107
     108    static QStringList removePaths(QOS2FileSystemWatcherEngine *engine,
     109                                   const QStringList &paths,
     110                                   QStringList *files,
     111                                   QStringList *directories);
     112
     113    static void removePaths(QOS2FileSystemWatcherEngine *engine);
     114
     115    static bool isOk() { return instance->notifyPipe != NULLHANDLE; }
     116
     117private:
     118
     119    QOS2FileSysWatcherThread();
     120    ~QOS2FileSysWatcherThread();
     121
     122    void run();
     123
     124    int refcnt;
     125
     126    bool finish;
     127    HFILE notifyPipe;
     128    HEV eventSem;
     129
     130    enum Type { None = 0, Dir, File };
     131    struct PathInfo
     132    {
     133        PathInfo(QString &p, Type t, QOS2FileSystemWatcherEngine *e = 0)
     134            : path(p), type(t) { if (e) engines.append(e); }
     135        QString path;
     136        Type type;
     137        QList<QOS2FileSystemWatcherEngine *> engines;
     138    };
     139    QHash<QString, QList<PathInfo> > watchedPaths;
     140
     141    static QOS2FileSysWatcherThread *instance;
     142    static QMutex mutex;
     143};
     144
     145// static
     146QOS2FileSysWatcherThread *QOS2FileSysWatcherThread::instance = 0;
     147QMutex QOS2FileSysWatcherThread::mutex;
     148
     149// static
     150void QOS2FileSysWatcherThread::addRef()
     151{
     152    QMutexLocker locker(&mutex);
     153
     154    if (instance == 0) {
     155        instance = new QOS2FileSysWatcherThread();
     156    }
     157
     158    ++instance->refcnt;
     159}
     160
     161// static
     162void QOS2FileSysWatcherThread::release()
     163{
     164    QMutexLocker locker(&mutex);
     165
     166    Q_ASSERT(instance);
     167
     168    if (--instance->refcnt == 0) {
     169        // make sure we don't globally exist anymore before leaving the lock
     170        QOS2FileSysWatcherThread *instance = QOS2FileSysWatcherThread::instance;
     171        QOS2FileSysWatcherThread::instance = 0;
     172        if (instance->isRunning()) {
     173            // stop the thread
     174            instance->finish = true;
     175            locker.unlock();
     176            DosPostEventSem(instance->eventSem);
     177            instance->wait();
     178        }
     179        delete instance;
     180    }
     181}
     182
     183QOS2FileSysWatcherThread::QOS2FileSysWatcherThread()
     184    : refcnt(0), finish(false), notifyPipe(NULLHANDLE), eventSem(NULLHANDLE)
    98185{
    99186    ULONG dummy, retries = 3;
     
    138225}
    139226
    140 QOS2FileSystemWatcherEngine::~QOS2FileSystemWatcherEngine()
    141 {
     227QOS2FileSysWatcherThread::~QOS2FileSysWatcherThread()
     228{
     229    Q_ASSERT(!refcnt);
     230    Q_ASSERT(!watchedPaths.size());
     231
    142232    if (notifyPipe != NULLHANDLE) {
    143233        DosCloseEventSem(eventSem);
     
    146236}
    147237
    148 QStringList QOS2FileSystemWatcherEngine::addPaths(const QStringList &paths,
    149                                                   QStringList *files,
    150                                                   QStringList *directories)
     238QStringList QOS2FileSysWatcherThread::addPaths(QOS2FileSystemWatcherEngine *engine,
     239                                               const QStringList &paths,
     240                                               QStringList *files,
     241                                               QStringList *directories)
    151242{
    152243    QMutexLocker locker(&mutex);
     
    159250        if (!fi.exists())
    160251            continue;
     252
    161253        QString normalPath = fi.absoluteFilePath();
    162254        normalPath = QDir::toNativeSeparators(QDir::cleanPath(path)).toUpper();
     
    171263                files->append(path);
    172264        }
    173         QList<PathInfo> &variants = watchedPaths[normalPath];
     265
     266        QList<PathInfo> &variants = instance->watchedPaths[normalPath];
    174267        bool alreadyAdded = false;
    175         foreach (const PathInfo &pi, variants) {
    176             if (pi.path == path) {
    177                 alreadyAdded = true;
    178                 break;
     268        for (QList<PathInfo>::iterator pathIt = variants.begin();
     269             pathIt != variants.end(); ++pathIt) {
     270            if (pathIt->path == path) {
     271                if (pathIt->engines.contains(engine)) {
     272                    alreadyAdded = true;
     273                    break;
     274                }
     275                pathIt->engines.append(engine);
    179276            }
    180277        }
     
    182279            continue;
    183280
    184         variants << PathInfo(path, type);
     281        variants << PathInfo(path, type);
    185282        it.remove();
    186283    }
    187284
    188     if (!isRunning) {
     285    if (!i) {
    189286        // (re)start the watcher thread
    190         isRunning = true;
    191         start(IdlePriority);
     287        ie;
     288        start(IdlePriority);
    192289    }
    193290
     
    195292}
    196293
    197 QStringList QOS2FileSystemWatcherEngine::removePaths(const QStringList &paths,
    198                                                      QStringList *files,
    199                                                      QStringList *directories)
     294QStringList QOS2FileSysWatcherThread::removePaths(QOS2FileSystemWatcherEngine *engine,
     295                                                  const QStringList &paths,
     296                                                  QStringList *files,
     297                                                  QStringList *directories)
    200298{
    201299    QMutexLocker locker(&mutex);
     
    207305        QString normalPath = QDir::current().absoluteFilePath(path);
    208306        normalPath = QDir::toNativeSeparators(QDir::cleanPath(path)).toUpper();
    209         if (watchedPaths.contains(normalPath)) {
    210             QList<PathInfo> &variants = watchedPaths[normalPath];
     307
     308        if (instance->watchedPaths.contains(normalPath)) {
     309            QList<PathInfo> &variants = instance->watchedPaths[normalPath];
     310
    211311            for (QList<PathInfo>::iterator pathIt = variants.begin();
    212312                 pathIt != variants.end(); ++pathIt) {
    213                 if (pathIt->path == path) {
     313                if (pathIt->path == path) {
    214314                    files->removeAll(path);
    215315                    directories->removeAll(path);
    216                     variants.erase(pathIt);
     316                    pathIt->engines.removeAll(engine);
     317                    if (pathIt->engines.isEmpty())
     318                        variants.erase(pathIt);
    217319                    it.remove();
    218320                    break;
    219321                }
    220322            }
     323
    221324            if (variants.isEmpty())
    222                 watchedPaths.remove(normalPath);
    223         }
    224     }
    225 
    226     if (watchedPaths.isEmpty()) {
     325                watchedPaths.remove(normalPath);
     326        }
     327    }
     328
     329    if (watchedPaths.isEmpty()) {
    227330        // stop the thread
    228         isRunning = false;
    229         DosPostEventSem(eventSem);
     331        ie;
     332        DosPostEventSem(eventSem);
    230333    }
    231334
     
    233336}
    234337
    235 void QOS2FileSystemWatcherEngine::run()
     338void QOS2FileSysWatcherThread::removePaths(QOS2FileSystemWatcherEngine *engine)
     339{
     340    QMutexLocker locker(&mutex);
     341
     342    foreach (const QString &normalPath, instance->watchedPaths.keys()) {
     343        QList<PathInfo> &variants = instance->watchedPaths[normalPath];
     344        for (QList<PathInfo>::iterator pathIt = variants.begin();
     345             pathIt != variants.end(); ++pathIt) {
     346            if (pathIt->engines.contains(engine)) {
     347                pathIt->engines.removeAll(engine);
     348                if (pathIt->engines.isEmpty())
     349                    variants.erase(pathIt);
     350                break;
     351            }
     352        }
     353
     354        if (variants.isEmpty())
     355            instance->watchedPaths.remove(normalPath);
     356    }
     357
     358    if (instance->watchedPaths.isEmpty()) {
     359        // stop the thread
     360        instance->finish = true;
     361        DosPostEventSem(instance->eventSem);
     362    }
     363}
     364
     365void QOS2FileSysWatcherThread::run()
    236366{
    237367    QByteArray buffer(sizeof(CNINFO) + _MAX_PATH + 2, 0);
     
    247377        locker.relock();
    248378
    249         if (!isRunning)
     379        if ()
    250380            break;
    251381
     
    299429                                type = pi.type;
    300430                            if (type == pi.type) {
    301                                 if (type == File)
    302                                     emit fileChanged(pi.path, deleted);
    303                                 else
    304                                     emit directoryChanged(pi.path, deleted);
     431                                foreach(QOS2FileSystemWatcherEngine *e, pi.engines) {
     432                                    if (type == File)
     433                                        e->doFileChanged(pi.path, deleted);
     434                                    else
     435                                        e->doDirectoryChanged(pi.path, deleted);
     436                                }
    305437                            }
    306438                        }
     
    316448                        foreach(const PathInfo &pi, watchedPaths[normalPath]) {
    317449                            if (pi.type == Dir)
    318                                 emit directoryChanged(pi.path, false);
     450                                foreach(QOS2FileSystemWatcherEngine *e, pi.engines)
     451                                    e->doDirectoryChanged(pi.path, false);
    319452                        }
    320453                    }
     
    334467}
    335468
     469
     470
     471
     472
     473
     474
     475
     476
     477
     478
     479
     480
     481
     482
     483
     484
     485
     486
     487
     488
     489
     490
     491
     492
    336493void QOS2FileSystemWatcherEngine::stop()
    337494{
    338     QMutexLocker locker(&mutex);
    339     if (isRunning) {
    340         isRunning = false;
    341         DosPostEventSem(eventSem);
    342         // note: the caller of stop() will wait() if necessary
    343     }
     495    Q);
     496}
     497
     498bool QOS2FileSystemWatcherEngine::isOk() const
     499{
     500   
    344501}
    345502
  • trunk/src/corelib/io/qfilesystemwatcher_os2_p.h

    r805 r944  
    6868class QOS2FileSystemWatcherEngine : public QFileSystemWatcherEngine
    6969{
    70     Q_OBJECT
    7170public:
    7271    QOS2FileSystemWatcherEngine();
     
    7877                            QStringList *directories);
    7978
    80     void run();
    8179    void stop();
     80
    8281
    83     bool isOk() const { return notifyPipe != NULLHANDLE; };
    84 
    85 private:
    86     mutable QMutex mutex;
    87     HFILE notifyPipe;
    88     HEV eventSem;
    89     bool isRunning;
    90 
    91     enum Type { None = 0, Dir, File };
    92     struct PathInfo
    93     {
    94         PathInfo(const QString &p, Type t) : path(p), type(t) {}
    95         QString path;
    96         Type type;
    97     };
    98     QHash<QString, QList<PathInfo> > watchedPaths;
     82    void doFileChanged(const QString &path, bool removed) {
     83        emit fileChanged(path, removed);
     84    }
     85    void doDirectoryChanged(const QString &path, bool removed) {
     86        emit directoryChanged(path, removed);
     87    }
    9988};
    10089
Note: See TracChangeset for help on using the changeset viewer.