// wait for events to occur, read them and send to interested parties // returns false it empty status was read, which means we whould exit // true otherwise bool wxIOCPThread::ReadEvents() { unsigned long count = 0; wxFSWatchEntryMSW* watch = NULL; OVERLAPPED* overlapped = NULL; if (!m_iocp->GetStatus(&count, &watch, &overlapped)) return true; // error was logged already, we don't want to exit // this is our exit condition, so we return false if (!count && !watch && !overlapped) return false; // in case of spurious wakeup if (!count || !watch) return true; wxLogTrace( wxTRACE_FSWATCHER, "[iocp] Read entry: path='%s'", watch->GetPath()); // First check if we're still interested in this watch, we could have // removed it in the meanwhile. if ( m_iocp->CompleteRemoval(watch) ) return true; // extract events from buffer info our vector container wxVector<wxEventProcessingData> events; const char* memory = static_cast<const char*>(watch->GetBuffer()); int offset = 0; do { const FILE_NOTIFY_INFORMATION* e = static_cast<const FILE_NOTIFY_INFORMATION*>((const void*)memory); events.push_back(wxEventProcessingData(e, watch)); offset = e->NextEntryOffset; memory += offset; } while (offset); // process events ProcessNativeEvents(events); // reissue the watch. ignore possible errors, we will return true anyway (void) m_service->SetUpWatch(*watch); return true; }
// wait for events to occur, read them and send to interested parties // returns false it empty status was read, which means we whould exit // true otherwise bool wxIOCPThread::ReadEvents() { unsigned long count = 0; wxFSWatchEntryMSW* watch = NULL; OVERLAPPED* overlapped = NULL; switch ( m_iocp->GetStatus(&count, &watch, &overlapped) ) { case wxIOCPService::Status_OK: break; // nothing special to do, continue normally case wxIOCPService::Status_Error: return true; // error was logged already, we don't want to exit case wxIOCPService::Status_Deleted: { wxFileSystemWatcherEvent removeEvent(wxFSW_EVENT_DELETE, watch->GetPath(), wxFileName()); SendEvent(removeEvent); } // It isn't useful to continue watching this directory as it // doesn't exist any more -- and even recreating a directory with // the same name still wouldn't resume generating events for the // existing wxIOCPService, so it's useless to continue. return false; case wxIOCPService::Status_Exit: return false; // stop reading events } // if the thread got woken up but we got an empty packet it means that // there was an overflow, too many events and not all could fit in // the watch buffer. In this case, ReadDirectoryChangesW dumps the // buffer. if (!count && watch) { wxLogTrace(wxTRACE_FSWATCHER, "[iocp] Event queue overflowed: path=\"%s\"", watch->GetPath()); if (watch->GetFlags() & wxFSW_EVENT_WARNING) { wxFileSystemWatcherEvent overflowEvent(wxFSW_EVENT_WARNING, wxFSW_WARNING_OVERFLOW); overflowEvent.SetPath(watch->GetPath()); SendEvent(overflowEvent); } // overflow is not a fatal error, we still want to get future events // reissue the watch (void) m_service->SetUpWatch(*watch); return true; } // in case of spurious wakeup if (!count || !watch) return true; wxLogTrace( wxTRACE_FSWATCHER, "[iocp] Read entry: path='%s'", watch->GetPath()); // First check if we're still interested in this watch, we could have // removed it in the meanwhile. if ( m_iocp->CompleteRemoval(watch) ) return true; // extract events from buffer info our vector container wxVector<wxEventProcessingData> events; const char* memory = static_cast<const char*>(watch->GetBuffer()); int offset = 0; do { const FILE_NOTIFY_INFORMATION* e = static_cast<const FILE_NOTIFY_INFORMATION*>((const void*)memory); events.push_back(wxEventProcessingData(e, watch)); offset = e->NextEntryOffset; memory += offset; } while (offset); // process events ProcessNativeEvents(events); // reissue the watch. ignore possible errors, we will return true anyway (void) m_service->SetUpWatch(*watch); return true; }