X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6b8ef0b35d674bc262eb2005ac1321762c831d31..0d53638f7147c18153f63fdfc096b17be6e22a27:/src/unix/fswatcher_kqueue.cpp diff --git a/src/unix/fswatcher_kqueue.cpp b/src/unix/fswatcher_kqueue.cpp index ccadcb6090..2bc1634dfc 100644 --- a/src/unix/fswatcher_kqueue.cpp +++ b/src/unix/fswatcher_kqueue.cpp @@ -3,7 +3,6 @@ // Purpose: kqueue-based wxFileSystemWatcher implementation // Author: Bartosz Bekier // Created: 2009-05-26 -// RCS-ID: $Id$ // Copyright: (c) 2009 Bartosz Bekier // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -23,9 +22,37 @@ #include #include + #include "wx/dynarray.h" +#include "wx/evtloop.h" +#include "wx/evtloopsrc.h" + #include "wx/private/fswatcher.h" +// ============================================================================ +// wxFSWSourceHandler helper class +// ============================================================================ + +class wxFSWatcherImplKqueue; + +/** + * Handler for handling i/o from inotify descriptor + */ +class wxFSWSourceHandler : public wxEventLoopSourceHandler +{ +public: + wxFSWSourceHandler(wxFSWatcherImplKqueue* service) : + m_service(service) + { } + + virtual void OnReadWaiting(); + virtual void OnWriteWaiting(); + virtual void OnExceptionWaiting(); + +protected: + wxFSWatcherImplKqueue* m_service; +}; + // ============================================================================ // wxFSWatcherImpl implementation & helper wxFSWSourceHandler implementation // ============================================================================ @@ -38,14 +65,13 @@ class wxFSWatcherImplKqueue : public wxFSWatcherImpl public: wxFSWatcherImplKqueue(wxFileSystemWatcherBase* watcher) : wxFSWatcherImpl(watcher), - m_loop(NULL), m_source(NULL), m_kfd(-1) { m_handler = new wxFSWSourceHandler(this); } - ~wxFSWatcherImplKqueue() + virtual ~wxFSWatcherImplKqueue() { // we close kqueue only if initialized before if (IsOk()) @@ -60,10 +86,9 @@ public: { wxCHECK_MSG( !IsOk(), false, "Kqueue appears to be already initialized" ); - wxCHECK_MSG( m_loop == NULL, false, "Event loop != NULL"); - m_loop = (wxEventLoopBase::GetActive()); - wxCHECK_MSG( m_loop, false, "File system watcher needs an active loop" ); + wxEventLoopBase *loop = wxEventLoopBase::GetActive(); + wxCHECK_MSG( loop, false, "File system watcher needs an active loop" ); // create kqueue m_kfd = kqueue(); @@ -74,32 +99,22 @@ public: } // create source - int flags = wxEVENT_SOURCE_INPUT; - m_source = m_loop->CreateSource(m_kfd, m_handler, flags); - wxCHECK_MSG( m_source, false, - "Active loop has no support for fd-based sources" ); + m_source = loop->AddSourceForFD(m_kfd, m_handler, wxEVENT_SOURCE_INPUT); - return RegisterSource(); + return m_source != NULL; } - bool Close() + void Close() { - wxCHECK_MSG( IsOk(), false, + wxCHECK_RET( IsOk(), "Kqueue not initialized or invalid kqueue descriptor" ); - wxCHECK_MSG( m_loop, false, - "m_loop shouldn't be null if kqueue is initialized" ); - - // ignore errors - (void) UnregisterSource(); - int ret = close(m_kfd); - if (ret == -1) + if ( close(m_kfd) != 0 ) { - wxLogSysError(_("Unable to close kqueue instance")); + wxLogSysError(_("Error closing kqueue instance")); } - m_source->Invalidate(); - return ret != -1; + wxDELETE(m_source); } virtual bool DoAdd(wxSharedPtr watch) @@ -133,8 +148,7 @@ public: // TODO more error conditions according to man // XXX closing file descriptor removes the watch. The logic resides in // the watch which is not nice, but effective and simple - bool ret = watch->Close(); - if (ret == -1) + if ( !watch->Close() ) { wxLogSysError(_("Unable to remove kqueue watch")); return false; @@ -186,43 +200,18 @@ public: return true; } - bool IsOk() + bool IsOk() const { - return m_source && m_source->IsOk(); + return m_source != NULL; } -/* - wxAbstractEventLoopSource* GetSource() const - { - return m_source; - }*/ - protected: - bool RegisterSource() - { - wxCHECK_MSG( IsOk(), false, - "Kqueue not initialized or invalid kqueue descriptor" ); - - return m_loop->AddSource(m_source); - } - - bool UnregisterSource() - { - wxCHECK_MSG( IsOk(), false, - "Kqueue not initialized or invalid kqueue descriptor" ); - wxCHECK_MSG( m_loop, false, - "m_loop shouldn't be null if kqueue is initialized" ); - - bool ret = m_loop->RemoveSource(m_source); - m_loop = NULL; - return ret; - } - // returns all new dirs/files present in the immediate level of the dir // pointed by watch.GetPath(). "new" means created between the last time // the state of watch was computed and now - void FindChanges(wxFSWatchEntryKq& watch, wxArrayString& changedFiles, - wxArrayInt& changedFlags) + void FindChanges(wxFSWatchEntryKq& watch, + wxArrayString& changedFiles, + wxArrayInt& changedFlags) { wxFSWatchEntryKq::wxDirState old = watch.GetLastState(); watch.RefreshState(); @@ -306,7 +295,8 @@ protected: while ( nflags ) { // when monitoring dir, this means create/delete - if ( nflags & NOTE_WRITE && wxDirExists(w.GetPath()) ) + const wxString basepath = w.GetPath(); + if ( nflags & NOTE_WRITE && wxDirExists(basepath) ) { // NOTE_LINK is set when the dir was created, but we // don't care - we look for new names in directory @@ -317,19 +307,17 @@ protected: wxArrayString changedFiles; wxArrayInt changedFlags; FindChanges(w, changedFiles, changedFlags); + wxArrayString::iterator it = changedFiles.begin(); wxArrayInt::iterator changeType = changedFlags.begin(); for ( ; it != changedFiles.end(); ++it, ++changeType ) { - wxFileName path; - if ( wxDirExists(*it) ) - { - path = wxFileName::DirName(w.GetPath() + *it); - } - else - { - path = wxFileName::FileName(w.GetPath() + *it); - } + const wxString fullpath = w.GetPath() + + wxFileName::GetPathSeparator() + + *it; + const wxFileName path(wxDirExists(fullpath) + ? wxFileName::DirName(fullpath) + : wxFileName::FileName(fullpath)); wxFileSystemWatcherEvent event(*changeType, path, path); SendEvent(event); @@ -342,28 +330,28 @@ protected: // still we couldn't be sure we have the right name... nflags &= ~NOTE_RENAME; wxFileSystemWatcherEvent event(wxFSW_EVENT_RENAME, - w.GetPath(), wxFileName()); + basepath, wxFileName()); SendEvent(event); } else if ( nflags & NOTE_WRITE || nflags & NOTE_EXTEND ) { nflags &= ~(NOTE_WRITE | NOTE_EXTEND); wxFileSystemWatcherEvent event(wxFSW_EVENT_MODIFY, - w.GetPath(), w.GetPath()); + basepath, basepath); SendEvent(event); } else if ( nflags & NOTE_DELETE ) { nflags &= ~(NOTE_DELETE); wxFileSystemWatcherEvent event(wxFSW_EVENT_DELETE, - w.GetPath(), w.GetPath()); + basepath, basepath); SendEvent(event); } else if ( nflags & NOTE_ATTRIB ) { nflags &= ~(NOTE_ATTRIB); wxFileSystemWatcherEvent event(wxFSW_EVENT_ACCESS, - w.GetPath(), w.GetPath()); + basepath, basepath); SendEvent(event); } @@ -386,8 +374,9 @@ protected: } wxFSWSourceHandler* m_handler; // handler for kqueue event source - wxEventLoopBase* m_loop; // event loop we have registered with - wxAbstractEventLoopSource* m_source; // our event loop source + wxEventLoopSource* m_source; // our event loop source + + // descriptor created by kqueue() int m_kfd; }; @@ -426,11 +415,7 @@ wxKqueueFileSystemWatcher::wxKqueueFileSystemWatcher(const wxFileName& path, { if (!Init()) { - if (m_service) - { - delete m_service; - m_service = NULL; - } + wxDELETE(m_service); return; }