]> git.saurik.com Git - wxWidgets.git/commitdiff
added wxFDIODispatcher::HasPending() and implemented correctly wxConsoleEventLoop...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 3 Jan 2009 01:21:24 +0000 (01:21 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 3 Jan 2009 01:21:24 +0000 (01:21 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57804 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/private/fdiodispatcher.h
include/wx/private/selectdispatcher.h
include/wx/unix/private/epolldispatcher.h
src/common/selectdispatcher.cpp
src/unix/epolldispatcher.cpp
src/unix/evtloopunix.cpp

index e7f367c1ffa42acc05d5231743abb203482bfa57..f37e0217a457e8a9dbfdcdd508e049de8b8b78bb 100644 (file)
@@ -67,10 +67,13 @@ public:
     // unregister descriptor previously registered with RegisterFD()
     virtual bool UnregisterFD(int fd) = 0;
 
+    // check if any events are currently available without dispatching them
+    virtual bool HasPending() const = 0;
+
     // wait for an event for at most timeout milliseconds and process it;
-    // return true if we processed any events or false if timeout expired
-    // without anything happening
-    virtual bool Dispatch(int timeout = TIMEOUT_INFINITE) = 0;
+    // return the number of events processed (possibly 0 if timeout expired) or
+    // -1 if an error occurred
+    virtual int Dispatch(int timeout = TIMEOUT_INFINITE) = 0;
 
     virtual ~wxFDIODispatcher() { }
 };
index a704b8a83cbc90c419e3680ccef270319bf104ee..1dc1ed290fd891e75b64292b77ffd6c897e952bd 100644 (file)
@@ -56,8 +56,9 @@ public:
     // select() itself
     int Select(int nfds, struct timeval *tv);
 
-    // call the handler methods corresponding to the sets having this fd
-    void Handle(int fd, wxFDIOHandler& handler) const;
+    // call the handler methods corresponding to the sets having this fd if it
+    // is present in any set and return true if it is
+    bool Handle(int fd, wxFDIOHandler& handler) const;
 
 private:
     typedef void (wxFDIOHandler::*Callback)();
@@ -91,20 +92,25 @@ public:
     virtual bool RegisterFD(int fd, wxFDIOHandler *handler, int flags = wxFDIO_ALL);
     virtual bool ModifyFD(int fd, wxFDIOHandler *handler, int flags = wxFDIO_ALL);
     virtual bool UnregisterFD(int fd);
-    virtual bool Dispatch(int timeout = TIMEOUT_INFINITE);
+    virtual bool HasPending() const;
+    virtual int Dispatch(int timeout = TIMEOUT_INFINITE);
 
 private:
     // common part of RegisterFD() and ModifyFD()
     bool DoUpdateFDAndHandler(int fd, wxFDIOHandler *handler, int flags);
 
-    // call the handlers for the fds present in the given sets, return true if
-    // we called any handlers
-    bool ProcessSets(const wxSelectSets& sets);
+    // call the handlers for the fds present in the given sets, return the
+    // number of handlers we called
+    int ProcessSets(const wxSelectSets& sets);
 
     // helper of ProcessSets(): call the handler if its fd is in the set
     void DoProcessFD(int fd, const fd_set& fds, wxFDIOHandler *handler,
                      const char *name);
 
+    // common part of HasPending() and Dispatch(): calls select() with the
+    // specified timeout
+    int DoSelect(wxSelectSets& sets, int timeout) const;
+
 
     // the select sets containing all the registered fds
     wxSelectSets m_sets;
index d689ea243cd3c0ea9b8fa5e0fb265cf9e50e74c0..a6786cf017660bc265d9a1b87a933e032a2bee23 100644 (file)
@@ -17,6 +17,8 @@
 
 #include "wx/private/fdiodispatcher.h"
 
+struct epoll_event;
+
 class WXDLLIMPEXP_CORE wxEpollDispatcher : public wxFDIODispatcher
 {
 public:
@@ -32,12 +34,18 @@ public:
     virtual bool RegisterFD(int fd, wxFDIOHandler* handler, int flags = wxFDIO_ALL);
     virtual bool ModifyFD(int fd, wxFDIOHandler* handler, int flags = wxFDIO_ALL);
     virtual bool UnregisterFD(int fd);
-    virtual bool Dispatch(int timeout = TIMEOUT_INFINITE);
+    virtual bool HasPending() const;
+    virtual int Dispatch(int timeout = TIMEOUT_INFINITE);
 
 private:
     // ctor is private, use Create()
     wxEpollDispatcher(int epollDescriptor);
 
+    // common part of HasPending() and Dispatch(): calls epoll_wait() with the
+    // given timeout
+    int DoPoll(epoll_event *events, int numEvents, int timeout) const;
+
+
     int m_epollDescriptor;
 };
 
index 990b62c21c0fdf7eceae51b87574fe67f586a06a..1365319347931940c1a4d09348e9d957cdf678b3 100644 (file)
@@ -111,7 +111,7 @@ 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++ )
     {
@@ -122,9 +122,11 @@ void wxSelectSets::Handle(int fd, wxFDIOHandler& handler) const
             (handler.*ms_handlers[n])();
             // callback can modify sets and destroy handler
             // this forces that one event can be processed at one time
-            return;
+            return true;
         }
     }
+
+    return false;
 }
 
 // ----------------------------------------------------------------------------
@@ -190,9 +192,9 @@ bool wxSelectDispatcher::UnregisterFD(int fd)
     return true;
 }
 
-bool wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
+int wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
 {
-    bool gotEvent = false;
+    int numEvents = 0;
     for ( int fd = 0; fd <= m_maxFD; fd++ )
     {
         if ( !sets.HasFD(fd) )
@@ -205,15 +207,14 @@ bool wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
             continue;
         }
 
-        gotEvent = true;
-
-        sets.Handle(fd, *handler);
+        if ( sets.Handle(fd, *handler) )
+            numEvents++;
     }
 
-    return gotEvent;
+    return numEvents;
 }
 
-bool wxSelectDispatcher::Dispatch(int timeout)
+int wxSelectDispatcher::DoSelect(wxSelectSets& sets, int timeout) const
 {
     struct timeval tv,
                   *ptv;
@@ -228,29 +229,38 @@ bool wxSelectDispatcher::Dispatch(int timeout)
         ptv = NULL;
     }
 
-    wxSelectSets sets = m_sets;
+    int ret = sets.Select(m_maxFD + 1, ptv);
 
-    const int ret = sets.Select(m_maxFD + 1, ptv);
-    switch ( ret )
+    // 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;
+}
+
+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:
-            if ( ProcessSets(sets) )
-                return true;
+            return ProcessSets(sets);
     }
-
-    // nothing happened
-    return false;
 }
 
 #endif // wxUSE_SELECT_DISPATCHER
index 336506016ca8f258ce5f4693506d1f1baf3cd023..b5b7a8cce637ea71d59cab3bed05f7d205170e79 100644 (file)
@@ -159,10 +159,9 @@ bool wxEpollDispatcher::UnregisterFD(int fd)
     return true;
 }
 
-bool wxEpollDispatcher::Dispatch(int timeout)
+int
+wxEpollDispatcher::DoPoll(epoll_event *events, int numEvents, int timeout) const
 {
-    epoll_event events[16];
-
     // the code below relies on TIMEOUT_INFINITE being -1 so that we can pass
     // timeout value directly to epoll_wait() which interprets -1 as meaning to
     // wait forever and would need to be changed if the value of
@@ -170,33 +169,48 @@ bool wxEpollDispatcher::Dispatch(int timeout)
     wxCOMPILE_TIME_ASSERT( TIMEOUT_INFINITE == -1, UpdateThisCode );
 
     wxMilliClock_t timeEnd;
-    if ( timeout != -1 )
+    if ( timeout > 0 )
         timeEnd = wxGetLocalTimeMillis();
 
     int rc;
     for ( ;; )
     {
-        rc = epoll_wait(m_epollDescriptor, events, WXSIZEOF(events), timeout);
+        rc = epoll_wait(m_epollDescriptor, events, numEvents, timeout);
         if ( rc != -1 || errno != EINTR )
             break;
 
         // we got interrupted, update the timeout and restart
-        if ( timeout == -1 )
-            continue;
-
-        timeout = wxMilliClockToLong(timeEnd - wxGetLocalTimeMillis());
-        if ( timeout < 0 )
-            return false;
+        if ( timeout > 0 )
+        {
+            timeout = wxMilliClockToLong(timeEnd - wxGetLocalTimeMillis());
+            if ( timeout < 0 )
+                return 0;
+        }
     }
 
+    return rc;
+}
+
+bool wxEpollDispatcher::HasPending() const
+{
+    epoll_event event;
+    return DoPoll(&event, 1, 0) == 1;
+}
+
+int wxEpollDispatcher::Dispatch(int timeout)
+{
+    epoll_event events[16];
+
+    const int rc = DoPoll(events, WXSIZEOF(events), timeout);
+
     if ( rc == -1 )
     {
         wxLogSysError(_("Waiting for IO on epoll descriptor %d failed"),
                       m_epollDescriptor);
-        return false;
+        return -1;
     }
 
-    bool gotEvents = false;
+    int numEvents = 0;
     for ( epoll_event *p = events; p < events + rc; p++ )
     {
         wxFDIOHandler * const handler = (wxFDIOHandler *)(p->data.ptr);
@@ -219,10 +233,10 @@ bool wxEpollDispatcher::Dispatch(int timeout)
         else
             continue;
 
-        gotEvents = true;
+        numEvents++;
     }
 
-    return gotEvents;
+    return numEvents;
 }
 
 #endif // wxUSE_EPOLL_DISPATCHER
index 1d5c1dc1a080f8f5d605788c1a373b8afb460020..fbaa4c775a5f3811a3e701b50297dbb4fd8d8c79 100644 (file)
@@ -85,7 +85,7 @@ void wxConsoleEventLoop::PipeIOHandler::WakeUp()
 void wxConsoleEventLoop::PipeIOHandler::OnReadWaiting()
 {
     // got wakeup from child thread: read all data available in pipe just to
-    // make it empty (evevn though we write one byte at a time from WakeUp(),
+    // make it empty (even though we write one byte at a time from WakeUp(),
     // it could have been called several times)
     char buf[4];
     for ( ;; )
@@ -107,7 +107,9 @@ void wxConsoleEventLoop::PipeIOHandler::OnReadWaiting()
         }
     }
 
-    wxTheApp->ProcessPendingEvents();
+    // writing to the wake up pipe will make wxConsoleEventLoop return from
+    // wxFDIODispatcher::Dispatch() it might be currently blocking in, nothing
+    // else needs to be done
 }
 
 // ===========================================================================
@@ -144,7 +146,17 @@ wxConsoleEventLoop::wxConsoleEventLoop()
 
 bool wxConsoleEventLoop::Pending() const
 {
-    return wxTheApp->HasPendingEvents();
+    if ( m_dispatcher->HasPending() )
+        return true;
+
+#if wxUSE_TIMER
+    wxUsecClock_t nextTimer;
+    if ( wxTimerScheduler::Get().GetNext(&nextTimer) &&
+            !wxMilliClockToLong(nextTimer) )
+        return true;
+#endif // wxUSE_TIMER
+
+    return false;
 }
 
 bool wxConsoleEventLoop::Dispatch()
@@ -167,7 +179,7 @@ int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout)
     }
 #endif // wxUSE_TIMER
 
-    bool hadEvent = m_dispatcher->Dispatch(timeout);
+    bool hadEvent = m_dispatcher->Dispatch(timeout) > 0;
 
 #if wxUSE_TIMER
     if ( wxTimerScheduler::Get().NotifyExpired() )