X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1f12921dc97a067e9316836243bac71c39d00217..7344108e8a129a3f9b4df5ab0f98a1713db03b89:/include/wx/msw/private/fswatcher.h diff --git a/include/wx/msw/private/fswatcher.h b/include/wx/msw/private/fswatcher.h index 3265c81025..3392141efd 100644 --- a/include/wx/msw/private/fswatcher.h +++ b/include/wx/msw/private/fswatcher.h @@ -50,7 +50,7 @@ public: m_path); } } - delete m_overlapped; + free(m_overlapped); } bool IsOk() const @@ -78,10 +78,13 @@ private: // asynchronous watched with ReadDirectoryChangesW static HANDLE OpenDir(const wxString& path) { - HANDLE handle = CreateFile(path, FILE_LIST_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_WRITE | + HANDLE handle = CreateFile(path.t_str(), + FILE_LIST_DIRECTORY, + FILE_SHARE_READ | + FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, + NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); @@ -101,7 +104,6 @@ private: wxDECLARE_NO_COPY_CLASS(wxFSWatchEntryMSW); }; - // ============================================================================ // wxFSWatcherImplMSW helper classes implementations // ============================================================================ @@ -153,12 +155,54 @@ public: return m_watches.insert(val).second; } + // Removes a watch we're currently using. Notice that this doesn't happen + // immediately, CompleteRemoval() must be called later when it's really + // safe to delete the watch, i.e. after completion of the IO operation + // using it. + bool ScheduleForRemoval(const wxSharedPtr& watch) + { + wxCHECK_MSG( m_iocp != INVALID_HANDLE_VALUE, false, "IOCP not init" ); + wxCHECK_MSG( watch->IsOk(), false, "Invalid watch" ); + + const wxString path = watch->GetPath(); + wxFSWatchEntries::iterator it = m_watches.find(path); + wxCHECK_MSG( it != m_watches.end(), false, + "Can't remove a watch we don't use" ); + + // We can't just delete the watch here as we can have pending events + // for it and if we destroyed it now, we could get a dangling (or, + // worse, reused to point to another object) pointer in ReadEvents() so + // just remember that this one should be removed when CompleteRemoval() + // is called later. + m_removedWatches.insert(wxFSWatchEntries::value_type(path, watch)); + m_watches.erase(it); + + return true; + } + + // Really remove the watch previously passed to ScheduleForRemoval(). + // + // It's ok to call this for a watch that hadn't been removed before, in + // this case we'll just return false and do nothing. + bool CompleteRemoval(wxFSWatchEntryMSW* watch) + { + wxFSWatchEntries::iterator it = m_removedWatches.find(watch->GetPath()); + if ( it == m_removedWatches.end() ) + return false; + + // Removing the object from the map will result in deleting the watch + // itself as it's not referenced from anywhere else now. + m_removedWatches.erase(it); + + return true; + } + // post completion packet bool PostEmptyStatus() { wxCHECK_MSG( m_iocp != INVALID_HANDLE_VALUE, false, "IOCP not init" ); - int ret = PostQueuedCompletionStatus(m_iocp, 0, NULL, NULL); + int ret = PostQueuedCompletionStatus(m_iocp, 0, 0, NULL); if (!ret) { wxLogSysError(_("Unable to post completion status")); @@ -200,7 +244,13 @@ protected: } HANDLE m_iocp; + + // The hash containing all the wxFSWatchEntryMSW objects currently being + // watched keyed by their paths. wxFSWatchEntries m_watches; + + // Contains the watches which had been removed but are still pending. + wxFSWatchEntries m_removedWatches; };