Changeset 945
- Timestamp:
- Aug 5, 2011, 11:26:12 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/corelib/io/qfilesystemwatcher_os2.cpp
r944 r945 94 94 QT_BEGIN_NAMESPACE 95 95 96 // ----------------------------------------------------------------------------- 97 98 // we don't actually get RCNF_CHANGED from OS/2 when the file modification date 99 // or size changes (some really silly bug), so we need a poller thread that 100 // will query this information from time to time 101 class QOS2FileSysPollerThread : public QThread 102 { 103 private: 104 105 enum { PollingInterval = 1000 }; 106 107 friend class QOS2FileSysWatcherThread; 108 109 QOS2FileSysPollerThread(); 110 ~QOS2FileSysPollerThread(); 111 112 void addPaths(const QStringList &paths); 113 void removePaths(const QStringList &paths); 114 115 void run(); 116 117 void stop(QMutexLocker &locker); 118 void stop() { QMutexLocker locker(&mutex); stop(locker); } 119 120 bool finish; 121 HEV eventSem; 122 123 typedef QHash<QString, FILESTATUS3> PathMap; 124 PathMap watchedPaths; 125 QMutex mutex; 126 }; 127 96 128 class QOS2FileSysWatcherThread : public QThread 97 129 { … … 113 145 static void removePaths(QOS2FileSystemWatcherEngine *engine); 114 146 147 static void reportChanges(const QStringList &paths); 148 115 149 static bool isOk() { return instance->notifyPipe != NULLHANDLE; } 116 150 … … 121 155 122 156 void run(); 157 158 void stop(QMutexLocker &locker); 123 159 124 160 int refcnt; … … 127 163 HFILE notifyPipe; 128 164 HEV eventSem; 165 166 QOS2FileSysPollerThread poller; 129 167 130 168 enum Type { None = 0, Dir, File }; … … 143 181 }; 144 182 183 // ----------------------------------------------------------------------------- 184 185 QOS2FileSysPollerThread::QOS2FileSysPollerThread() 186 : finish(false), eventSem(NULLHANDLE) 187 { 188 APIRET arc; 189 arc = DosCreateEventSem(NULL, &eventSem, 190 DC_SEM_SHARED | DCE_AUTORESET | DCE_POSTONE, 191 FALSE); 192 Q_ASSERT(arc == NO_ERROR); 193 Q_UNUSED(arc); 194 } 195 196 QOS2FileSysPollerThread::~QOS2FileSysPollerThread() 197 { 198 Q_ASSERT(watchedPaths.isEmpty()); 199 200 if (eventSem) 201 DosCloseEventSem(eventSem); 202 } 203 204 void QOS2FileSysPollerThread::addPaths(const QStringList &paths) 205 { 206 APIRET arc; 207 FILESTATUS3 newInfo; 208 209 QMutexLocker locker(&mutex); 210 211 foreach (const QString &path, paths) { 212 arc = DosQueryPathInfo(QFile::encodeName(path), FIL_STANDARD, 213 &newInfo, sizeof(newInfo)); 214 if (arc == NO_ERROR) 215 watchedPaths.insert(path, newInfo); 216 } 217 218 if (!watchedPaths.isEmpty() && !isRunning()) { 219 // (re)start the thread 220 finish = false; 221 start(IdlePriority); 222 } 223 } 224 225 void QOS2FileSysPollerThread::removePaths(const QStringList &paths) 226 { 227 QMutexLocker locker(&mutex); 228 229 foreach (const QString &path, paths) { 230 watchedPaths.remove(path); 231 } 232 233 if (watchedPaths.isEmpty()) 234 stop(locker); 235 } 236 237 void QOS2FileSysPollerThread::run() 238 { 239 APIRET arc; 240 QStringList changedPaths; 241 242 QMutexLocker locker(&mutex); 243 244 forever { 245 locker.unlock(); 246 247 if (!changedPaths.isEmpty()) { 248 // important: must be done outside the lock to avoid the deadlock 249 // with QOS2FileSysWatcherThread that may be calling us 250 QOS2FileSysWatcherThread::reportChanges(changedPaths); 251 changedPaths.clear(); 252 } 253 254 qDosNI(arc = DosWaitEventSem(eventSem, PollingInterval)); 255 256 locker.relock(); 257 258 for (PathMap::iterator it = watchedPaths.begin(); 259 it != watchedPaths.end(); ++it) { 260 QString path = it.key(); 261 FILESTATUS3 &info = it.value(); 262 263 FILESTATUS3 newInfo; 264 arc = DosQueryPathInfo(QFile::encodeName(path), FIL_STANDARD, 265 &newInfo, sizeof(newInfo)); 266 if (arc != NO_ERROR) 267 continue; 268 269 if (memcmp(&newInfo.fdateLastWrite, 270 &info.fdateLastWrite, sizeof(FDATE)) != 0 || 271 newInfo.cbFile != info.cbFile || 272 newInfo.cbFileAlloc != info.cbFileAlloc || 273 newInfo.attrFile != info.attrFile) { 274 // there was a change, memorize it and update the info 275 changedPaths << path; 276 info = newInfo; 277 } 278 } 279 280 if (finish) 281 break; 282 } 283 } 284 285 void QOS2FileSysPollerThread::stop(QMutexLocker &locker) 286 { 287 Q_ASSERT(locker.locked()); 288 289 if (isRunning()) { 290 finish = true; 291 DosPostEventSem(eventSem); 292 locker.unlock(); 293 wait(); 294 } 295 } 296 297 // ----------------------------------------------------------------------------- 298 145 299 // static 146 300 QOS2FileSysWatcherThread *QOS2FileSysWatcherThread::instance = 0; … … 170 324 QOS2FileSysWatcherThread *instance = QOS2FileSysWatcherThread::instance; 171 325 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 } 326 instance->poller.stop(); 327 instance->stop(locker); 179 328 delete instance; 180 329 } … … 228 377 { 229 378 Q_ASSERT(!refcnt); 230 Q_ASSERT( !watchedPaths.size());379 Q_ASSERT(watchedPaths.isEmpty()); 231 380 232 381 if (notifyPipe != NULLHANDLE) { … … 236 385 } 237 386 387 // static 238 388 QStringList QOS2FileSysWatcherThread::addPaths(QOS2FileSystemWatcherEngine *engine, 239 389 const QStringList &paths, … … 243 393 QMutexLocker locker(&mutex); 244 394 245 QStringList p = paths ;395 QStringList p = paths, pollerPaths; 246 396 QMutableListIterator<QString> it(p); 247 397 while (it.hasNext()) { … … 264 414 } 265 415 416 if (!instance->watchedPaths.contains(normalPath)) 417 pollerPaths << normalPath; 418 266 419 QList<PathInfo> &variants = instance->watchedPaths[normalPath]; 267 bool alreadyAdded = false;420 bool found = false, alreadyAdded = false; 268 421 for (QList<PathInfo>::iterator pathIt = variants.begin(); 269 422 pathIt != variants.end(); ++pathIt) { 270 423 if (pathIt->path == path) { 271 if (pathIt->engines.contains(engine)) { 424 found = true; 425 if (pathIt->engines.contains(engine)) 272 426 alreadyAdded = true; 273 break;274 }275 pathIt->engines.append(engine);427 else 428 pathIt->engines.append(engine); 429 break; 276 430 } 277 431 } … … 279 433 continue; 280 434 281 variants << PathInfo(path, type, engine); 435 if (!found) 436 variants << PathInfo(path, type, engine); 282 437 it.remove(); 283 438 } … … 289 444 } 290 445 446 // add new normal paths to the poller 447 if (!pollerPaths.isEmpty()) 448 instance->poller.addPaths(pollerPaths); 449 291 450 return p; 292 451 } 293 452 453 // static 294 454 QStringList QOS2FileSysWatcherThread::removePaths(QOS2FileSystemWatcherEngine *engine, 295 455 const QStringList &paths, … … 299 459 QMutexLocker locker(&mutex); 300 460 301 QStringList p = paths ;461 QStringList p = paths, pollerPaths; 302 462 QMutableListIterator<QString> it(p); 303 463 while (it.hasNext()) { … … 322 482 } 323 483 324 if (variants.isEmpty()) 484 if (variants.isEmpty()) { 325 485 instance->watchedPaths.remove(normalPath); 326 } 327 } 328 329 if (instance->watchedPaths.isEmpty()) { 330 // stop the thread 331 instance->finish = true; 332 DosPostEventSem(instance->eventSem); 333 } 486 pollerPaths << normalPath; 487 } 488 } 489 } 490 491 // remove unwatched normal paths from the poller 492 if (!pollerPaths.isEmpty()) 493 instance->poller.removePaths(pollerPaths); 494 495 if (instance->watchedPaths.isEmpty()) 496 instance->stop(locker); 334 497 335 498 return p; 336 499 } 337 500 501 // static 338 502 void QOS2FileSysWatcherThread::removePaths(QOS2FileSystemWatcherEngine *engine) 339 503 { 340 504 QMutexLocker locker(&mutex); 341 505 506 QStringList pollerPaths; 342 507 foreach (const QString &normalPath, instance->watchedPaths.keys()) { 343 508 QList<PathInfo> &variants = instance->watchedPaths[normalPath]; … … 352 517 } 353 518 354 if (variants.isEmpty()) 519 if (variants.isEmpty()) { 355 520 instance->watchedPaths.remove(normalPath); 356 } 357 358 if (instance->watchedPaths.isEmpty()) { 359 // stop the thread 360 instance->finish = true; 361 DosPostEventSem(instance->eventSem); 521 pollerPaths << normalPath; 522 } 523 } 524 525 // remove unwatched normal paths from the poller 526 if (!pollerPaths.isEmpty()) 527 instance->poller.removePaths(pollerPaths); 528 529 if (instance->watchedPaths.isEmpty() && instance->isRunning()) 530 instance->stop(locker); 531 } 532 533 // static 534 void QOS2FileSysWatcherThread::reportChanges(const QStringList &paths) 535 { 536 QMutexLocker locker(&mutex); 537 538 foreach (const QString &path, paths) { 539 // signal the change 540 if (instance->watchedPaths.contains(path)) { 541 QList<PathInfo> &variants = instance->watchedPaths[path]; 542 foreach(const PathInfo &pi, variants) { 543 foreach(QOS2FileSystemWatcherEngine *e, pi.engines) { 544 if (pi.type == File) 545 e->doFileChanged(pi.path, false); 546 else 547 e->doDirectoryChanged(pi.path, false); 548 } 549 } 550 } 362 551 } 363 552 } … … 421 610 bool deleted = info->bAction != RCNF_CHANGED; 422 611 if (deleted) { 612 // make a copy as we will need to iterate over it 423 613 deletedVariants = variants; 424 614 variants = deletedVariants; 615 // remove the deleted path from watching 425 616 watchedPaths.remove(normalPath); 617 instance->poller.removePaths(QStringList(normalPath)); 426 618 } 427 619 foreach(const PathInfo &pi, variants) { … … 467 659 } 468 660 661 void QOS2FileSysWatcherThread::stop(QMutexLocker &locker) 662 { 663 Q_ASSERT(locker.locked()); 664 665 if (instance->isRunning()) { 666 // stop the thread 667 finish = true; 668 DosPostEventSem(eventSem); 669 locker.unlock(); 670 wait(); 671 } 672 } 673 674 // ----------------------------------------------------------------------------- 675 469 676 QOS2FileSystemWatcherEngine::QOS2FileSystemWatcherEngine() 470 677 {
Note:
See TracChangeset
for help on using the changeset viewer.