]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/fswatcher_kqueue.cpp
Fix wxHtmlHelpData::SetTempDir() to behave correctly without trailing slash.
[wxWidgets.git] / src / unix / fswatcher_kqueue.cpp
index ccadcb609007d7705e12cef473e6bdd2f7efd5ea..2bc1634dfc26281b697e0863a44c9c676517898c 100644 (file)
@@ -3,7 +3,6 @@
 // Purpose:     kqueue-based wxFileSystemWatcher implementation
 // Author:      Bartosz Bekier
 // Created:     2009-05-26
 // Purpose:     kqueue-based wxFileSystemWatcher implementation
 // Author:      Bartosz Bekier
 // Created:     2009-05-26
-// RCS-ID:      $Id$
 // Copyright:   (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 // Copyright:   (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 #include <sys/types.h>
 #include <sys/event.h>
 
 #include <sys/types.h>
 #include <sys/event.h>
+
 #include "wx/dynarray.h"
 #include "wx/dynarray.h"
+#include "wx/evtloop.h"
+#include "wx/evtloopsrc.h"
+
 #include "wx/private/fswatcher.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
 // ============================================================================
 // ============================================================================
 // wxFSWatcherImpl implementation & helper wxFSWSourceHandler implementation
 // ============================================================================
@@ -38,14 +65,13 @@ class wxFSWatcherImplKqueue : public wxFSWatcherImpl
 public:
     wxFSWatcherImplKqueue(wxFileSystemWatcherBase* watcher) :
         wxFSWatcherImpl(watcher),
 public:
     wxFSWatcherImplKqueue(wxFileSystemWatcherBase* watcher) :
         wxFSWatcherImpl(watcher),
-        m_loop(NULL),
         m_source(NULL),
         m_kfd(-1)
     {
         m_handler = new wxFSWSourceHandler(this);
     }
 
         m_source(NULL),
         m_kfd(-1)
     {
         m_handler = new wxFSWSourceHandler(this);
     }
 
-    ~wxFSWatcherImplKqueue()
+    virtual ~wxFSWatcherImplKqueue()
     {
         // we close kqueue only if initialized before
         if (IsOk())
     {
         // 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( !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();
 
         // create kqueue
         m_kfd = kqueue();
@@ -74,32 +99,22 @@ public:
         }
 
         // create source
         }
 
         // 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" );
                     "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<wxFSWatchEntryKq> watch)
     }
 
     virtual bool DoAdd(wxSharedPtr<wxFSWatchEntryKq> 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
         // 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;
         {
             wxLogSysError(_("Unable to remove kqueue watch"));
             return false;
@@ -186,43 +200,18 @@ public:
         return true;
     }
 
         return true;
     }
 
-    bool IsOk()
+    bool IsOk() const
     {
     {
-        return m_source && m_source->IsOk();
+        return m_source != NULL;
     }
 
     }
 
-/*
-    wxAbstractEventLoopSource* GetSource() const
-    {
-        return m_source;
-    }*/
-
 protected:
 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
     // 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();
     {
         wxFSWatchEntryKq::wxDirState old = watch.GetLastState();
         watch.RefreshState();
@@ -306,7 +295,8 @@ protected:
         while ( nflags )
         {
             // when monitoring dir, this means create/delete
         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
             {
                 // 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 changedFiles;
                 wxArrayInt changedFlags;
                 FindChanges(w, changedFiles, changedFlags);
+
                 wxArrayString::iterator it = changedFiles.begin();
                 wxArrayInt::iterator changeType = changedFlags.begin();
                 for ( ; it != changedFiles.end(); ++it, ++changeType )
                 {
                 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);
 
                     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,
                 // 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,
                 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,
                 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,
                 SendEvent(event);
             }
             else if ( nflags & NOTE_ATTRIB )
             {
                 nflags &= ~(NOTE_ATTRIB);
                 wxFileSystemWatcherEvent event(wxFSW_EVENT_ACCESS,
-                                        w.GetPath(), w.GetPath());
+                                        basepath, basepath);
                 SendEvent(event);
             }
 
                 SendEvent(event);
             }
 
@@ -386,8 +374,9 @@ protected:
     }
 
     wxFSWSourceHandler* m_handler;        // handler for kqueue event source
     }
 
     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;
 };
 
     int m_kfd;
 };
 
@@ -426,11 +415,7 @@ wxKqueueFileSystemWatcher::wxKqueueFileSystemWatcher(const wxFileName& path,
 {
     if (!Init())
     {
 {
     if (!Init())
     {
-        if (m_service)
-        {
-            delete m_service;
-            m_service = NULL;
-        }
+        wxDELETE(m_service);
         return;
     }
 
         return;
     }