]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/selectdispatcher.cpp
Rewind the input stream after failing to load image from it.
[wxWidgets.git] / src / common / selectdispatcher.cpp
index 654eee9f4a028c96871860dfb8e64f0364ee0366..fd0a26938cb2e328204842cee0cf00022b990afe 100644 (file)
@@ -5,7 +5,7 @@
 // Created:     December 2006
 // RCS-ID:      $Id$
 // Copyright:   (c) 2006 Lukasz Michalski
-// License:     wxWindows licence
+// Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 // for compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
 #if wxUSE_SELECT_DISPATCHER
 
 #include "wx/private/selectdispatcher.h"
-#include "wx/module.h"
 #include "wx/unix/private.h"
 
 #ifndef WX_PRECOMP
     #include "wx/intl.h"
 #endif
 
-#ifdef HAVE_SYS_SELECT_H
-    #include <sys/select.h>
-#endif
-
 #include <errno.h>
 
 #define wxSelectDispatcher_Trace wxT("selectdispatcher")
@@ -89,21 +88,17 @@ bool wxSelectSets::HasFD(int fd) const
 
 bool wxSelectSets::SetFD(int fd, int flags)
 {
-    wxCHECK_MSG( fd >= 0, false, _T("invalid descriptor") );
+    wxCHECK_MSG( fd >= 0, false, wxT("invalid descriptor") );
 
     for ( int n = 0; n < Max; n++ )
     {
         if ( flags & ms_flags[n] )
         {
             wxFD_SET(fd, &m_fds[n]);
-            wxLogTrace(wxSelectDispatcher_Trace,
-                       _T("Registered fd %d for %s events"), fd, ms_names[n]);
         }
         else if ( wxFD_ISSET(fd,  (fd_set*) &m_fds[n]) )
         {
             wxFD_CLR(fd, &m_fds[n]);
-            wxLogTrace(wxSelectDispatcher_Trace,
-                       _T("Unregistered fd %d from %s events"), fd, ms_names[n]);
         }
     }
 
@@ -115,50 +110,28 @@ int wxSelectSets::Select(int nfds, struct timeval *tv)
     return select(nfds, &m_fds[Read], &m_fds[Write], &m_fds[Except], tv);
 }
 
-void wxSelectSets::Handle(int fd, wxFDIOHandler& handler) const
+bool wxSelectSets::Handle(int fd, wxFDIOHandler& handler) const
 {
     for ( int n = 0; n < Max; n++ )
     {
         if ( wxFD_ISSET(fd, (fd_set*) &m_fds[n]) )
         {
             wxLogTrace(wxSelectDispatcher_Trace,
-                       _T("Got %s event on fd %d"), ms_names[n], fd);
+                       wxT("Got %s event on fd %d"), ms_names[n], fd);
             (handler.*ms_handlers[n])();
+            // callback can modify sets and destroy handler
+            // this forces that one event can be processed at one time
+            return true;
         }
     }
+
+    return false;
 }
 
 // ----------------------------------------------------------------------------
 // wxSelectDispatcher
 // ----------------------------------------------------------------------------
 
-static wxSelectDispatcher *gs_selectDispatcher = NULL;
-
-/* static */
-wxSelectDispatcher *wxSelectDispatcher::Get()
-{
-    if ( !gs_selectDispatcher )
-    {
-        // the dispatcher should be only created from one thread so it should
-        // be ok to use a global without any protection here
-        gs_selectDispatcher = new wxSelectDispatcher;
-    }
-
-    return gs_selectDispatcher;
-}
-
-/* static */
-void wxSelectDispatcher::DispatchPending()
-{
-    if ( gs_selectDispatcher )
-        gs_selectDispatcher->Dispatch(0);
-}
-
-wxSelectDispatcher::wxSelectDispatcher()
-{
-    m_maxFD = -1;
-}
-
 bool wxSelectDispatcher::RegisterFD(int fd, wxFDIOHandler *handler, int flags)
 {
     if ( !wxMappedFDIODispatcher::RegisterFD(fd, handler, flags) )
@@ -170,6 +143,8 @@ bool wxSelectDispatcher::RegisterFD(int fd, wxFDIOHandler *handler, int flags)
     if ( fd > m_maxFD )
       m_maxFD = fd;
 
+    wxLogTrace(wxSelectDispatcher_Trace,
+                wxT("Registered fd %d: input:%d, output:%d, exceptional:%d"), fd, (flags & wxFDIO_INPUT) == wxFDIO_INPUT, (flags & wxFDIO_OUTPUT), (flags & wxFDIO_EXCEPTION) == wxFDIO_EXCEPTION);
     return true;
 }
 
@@ -178,8 +153,10 @@ bool wxSelectDispatcher::ModifyFD(int fd, wxFDIOHandler *handler, int flags)
     if ( !wxMappedFDIODispatcher::ModifyFD(fd, handler, flags) )
         return false;
 
-    wxASSERT_MSG( fd <= m_maxFD, _T("logic error: registered fd > m_maxFD?") );
+    wxASSERT_MSG( fd <= m_maxFD, wxT("logic error: registered fd > m_maxFD?") );
 
+    wxLogTrace(wxSelectDispatcher_Trace,
+                wxT("Modified fd %d: input:%d, output:%d, exceptional:%d"), fd, (flags & wxFDIO_INPUT) == wxFDIO_INPUT, (flags & wxFDIO_OUTPUT) == wxFDIO_OUTPUT, (flags & wxFDIO_EXCEPTION) == wxFDIO_EXCEPTION);
     return m_sets.SetFD(fd, flags);
 }
 
@@ -202,16 +179,21 @@ bool wxSelectDispatcher::UnregisterFD(int fd)
                   ++it )
             {
                 if ( it->first > m_maxFD )
+                {
                     m_maxFD = it->first;
+                }
             }
         }
     }
 
+    wxLogTrace(wxSelectDispatcher_Trace,
+                wxT("Removed fd %d, current max: %d"), fd, m_maxFD);
     return true;
 }
 
-void wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
+int wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
 {
+    int numEvents = 0;
     for ( int fd = 0; fd <= m_maxFD; fd++ )
     {
         if ( !sets.HasFD(fd) )
@@ -220,64 +202,64 @@ void wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
         wxFDIOHandler * const handler = FindHandler(fd);
         if ( !handler )
         {
-            wxFAIL_MSG( _T("NULL handler in wxSelectDispatcher?") );
+            wxFAIL_MSG( wxT("NULL handler in wxSelectDispatcher?") );
             continue;
         }
 
-        sets.Handle(fd, *handler);
+        if ( sets.Handle(fd, *handler) )
+            numEvents++;
     }
+
+    return numEvents;
 }
 
-void wxSelectDispatcher::Dispatch(int timeout)
+int wxSelectDispatcher::DoSelect(wxSelectSets& sets, int timeout) const
 {
     struct timeval tv,
                   *ptv;
     if ( timeout != TIMEOUT_INFINITE )
     {
         ptv = &tv;
-        tv.tv_sec = 0;
-        tv.tv_usec = timeout*1000;
+        tv.tv_sec = timeout / 1000;
+        tv.tv_usec = (timeout % 1000)*1000;
     }
     else // no timeout
     {
         ptv = NULL;
     }
 
-    wxSelectSets sets = m_sets;
+    int ret = sets.Select(m_maxFD + 1, ptv);
+
+    // TODO: we need to restart select() in this case but for now just return
+    //       as if timeout expired
+    if ( ret == -1 && errno == EINTR )
+        ret = 0;
+
+    return ret;
+}
 
-    const int ret = sets.Select(m_maxFD + 1, ptv);
-    switch ( ret )
+bool wxSelectDispatcher::HasPending() const
+{
+    wxSelectSets sets(m_sets);
+    return DoSelect(sets, 0) > 0;
+}
+
+int wxSelectDispatcher::Dispatch(int timeout)
+{
+    wxSelectSets sets(m_sets);
+    switch ( DoSelect(sets, timeout) )
     {
         case -1:
-            if ( errno != EINTR )
-            {
-                wxLogSysError(_("Failed to monitor I/O channels"));
-            }
-            break;
+            wxLogSysError(_("Failed to monitor I/O channels"));
+            return -1;
 
         case 0:
             // timeout expired without anything happening
-            break;
+            return 0;
 
         default:
-            ProcessSets(sets);
+            return ProcessSets(sets);
     }
 }
 
-// ----------------------------------------------------------------------------
-// wxSelectDispatcherModule
-// ----------------------------------------------------------------------------
-
-class wxSelectDispatcherModule : public wxModule
-{
-public:
-    virtual bool OnInit() { return true; }
-    virtual void OnExit() { wxDELETE(gs_selectDispatcher); }
-
-private:
-    DECLARE_DYNAMIC_CLASS(wxSelectDispatcherModule)
-};
-
-IMPLEMENT_DYNAMIC_CLASS(wxSelectDispatcherModule, wxModule)
-
 #endif // wxUSE_SELECT_DISPATCHER