Revision: 4784
          http://tigervnc.svn.sourceforge.net/tigervnc/?rev=4784&view=rev
Author:   ossman_
Date:     2011-11-08 12:44:10 +0000 (Tue, 08 Nov 2011)
Log Message:
-----------
Reimplement the deferred update handling, this time in a more robust and
well-behaved manner.

Modified Paths:
--------------
    trunk/common/rfb/VNCSConnectionST.cxx
    trunk/common/rfb/VNCServer.h
    trunk/common/rfb/VNCServerST.cxx
    trunk/common/rfb/VNCServerST.h
    trunk/unix/x0vncserver/PollingManager.cxx
    trunk/unix/xserver/hw/vnc/Input.cc
    trunk/unix/xserver/hw/vnc/XserverDesktop.cc
    trunk/unix/xserver/hw/vnc/XserverDesktop.h
    trunk/win/rfb_win32/SDisplay.cxx

Modified: trunk/common/rfb/VNCSConnectionST.cxx
===================================================================
--- trunk/common/rfb/VNCSConnectionST.cxx       2011-11-08 12:42:41 UTC (rev 
4783)
+++ trunk/common/rfb/VNCSConnectionST.cxx       2011-11-08 12:44:10 UTC (rev 
4784)
@@ -668,7 +668,11 @@
 
   updates.enable_copyrect(cp.useCopyRect);
 
-  server->checkUpdate();
+  // Fetch updates from server object, and see if we are allowed to send
+  // anything right now (the framebuffer might have changed in ways we
+  // haven't yet been informed of).
+  if (!server->checkUpdate())
+    return;
 
   // Get the lists of updates. Prior to exporting the data to the `ui' object,
   // getUpdateInfo() will normalize the `updates' object such way that its

Modified: trunk/common/rfb/VNCServer.h
===================================================================
--- trunk/common/rfb/VNCServer.h        2011-11-08 12:42:41 UTC (rev 4783)
+++ trunk/common/rfb/VNCServer.h        2011-11-08 12:44:10 UTC (rev 4784)
@@ -62,10 +62,6 @@
     //   their close() method with the supplied reason.
     virtual void closeClients(const char* reason) = 0;
 
-    // tryUpdate() causes the server to attempt to send updates to any waiting
-    // clients.
-    virtual void tryUpdate() = 0;
-
     // setCursor() tells the server that the cursor has changed.  The
     // cursorData argument contains width*height pixel values in the pixel
     // buffer's format.  The mask argument is a bitmask with a 1-bit meaning

Modified: trunk/common/rfb/VNCServerST.cxx
===================================================================
--- trunk/common/rfb/VNCServerST.cxx    2011-11-08 12:42:41 UTC (rev 4783)
+++ trunk/common/rfb/VNCServerST.cxx    2011-11-08 12:44:10 UTC (rev 4784)
@@ -64,6 +64,12 @@
 static LogWriter slog("VNCServerST");
 LogWriter VNCServerST::connectionsLog("Connections");
 
+rfb::IntParameter deferUpdateTime("DeferUpdate",
+                                  "Time in milliseconds to defer updates",10);
+
+rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer",
+                  "Always reset the defer update timer on every change",false);
+
 //
 // -=- VNCServerST Implementation
 //
@@ -76,7 +82,8 @@
     renderedCursorInvalid(false),
     queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
     useEconomicTranslate(false),
-    lastConnectionTime(0), disableclients(false)
+    lastConnectionTime(0), disableclients(false),
+    deferTimer(this), deferPending(false)
 {
   lastUserInputTime = lastDisconnectTime = time(0);
   slog.debug("creating single-threaded server %s", name.buf);
@@ -373,25 +380,22 @@
 
 void VNCServerST::add_changed(const Region& region)
 {
-  if (comparer != 0) {
-    comparer->add_changed(region);
-  }
+  if (comparer == NULL)
+    return;
+
+  comparer->add_changed(region);
+  startDefer();
+  tryUpdate();
 }
 
 void VNCServerST::add_copied(const Region& dest, const Point& delta)
 {
-  if (comparer != 0) {
-    comparer->add_copied(dest, delta);
-  }
-}
+  if (comparer == NULL)
+    return;
 
-void VNCServerST::tryUpdate()
-{
-  std::list<VNCSConnectionST*>::iterator ci, ci_next;
-  for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
-    ci_next = ci; ci_next++;
-    (*ci)->writeFramebufferUpdateOrClose();
-  }
+  comparer->add_copied(dest, delta);
+  startDefer();
+  tryUpdate();
 }
 
 void VNCServerST::setCursor(int width, int height, const Point& newHotspot,
@@ -471,7 +475,16 @@
   return 0;
 }
 
+bool VNCServerST::handleTimeout(Timer* t)
+{
+  if (t != &deferTimer)
+    return false;
 
+  tryUpdate();
+
+  return false;
+}
+
 // -=- Internal methods
 
 void VNCServerST::startDesktop()
@@ -503,6 +516,44 @@
   return false;
 }
 
+inline void VNCServerST::startDefer()
+{
+  if (deferUpdateTime == 0)
+    return;
+
+  if (deferPending && !alwaysSetDeferUpdateTimer)
+    return;
+
+  gettimeofday(&deferStart, NULL);
+  deferTimer.start(deferUpdateTime);
+
+  deferPending = true;
+}
+
+inline bool VNCServerST::checkDefer()
+{
+  if (!deferPending)
+    return true;
+
+  if (msSince(&deferStart) >= deferUpdateTime)
+    return true;
+
+  return false;
+}
+
+void VNCServerST::tryUpdate()
+{
+  std::list<VNCSConnectionST*>::iterator ci, ci_next;
+
+  if (!checkDefer())
+    return;
+
+  for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
+    ci_next = ci; ci_next++;
+    (*ci)->writeFramebufferUpdateOrClose();
+  }
+}
+
 // checkUpdate() is called just before sending an update.  It checks to see
 // what updates are pending and propagates them to the update tracker for each
 // client.  It uses the ComparingUpdateTracker's compare() method to filter out
@@ -510,7 +561,7 @@
 // state of the (server-side) rendered cursor, if necessary rendering it again
 // with the correct background.
 
-void VNCServerST::checkUpdate()
+bool VNCServerST::checkUpdate()
 {
   UpdateInfo ui;
   comparer->getUpdateInfo(&ui, pb->getRect());
@@ -518,8 +569,14 @@
   bool renderCursor = needRenderedCursor();
 
   if (ui.is_empty() && !(renderCursor && renderedCursorInvalid))
-    return;
+    return true;
 
+  // Block client from updating if we are currently deferring updates
+  if (!checkDefer())
+    return false;
+
+  deferPending = false;
+
   Region toCheck = ui.changed.union_(ui.copied);
 
   if (renderCursor) {
@@ -561,6 +618,8 @@
   }
 
   comparer->clear();
+
+  return true;
 }
 
 void VNCServerST::getConnInfo(ListConnInfo * listConn)

Modified: trunk/common/rfb/VNCServerST.h
===================================================================
--- trunk/common/rfb/VNCServerST.h      2011-11-08 12:42:41 UTC (rev 4783)
+++ trunk/common/rfb/VNCServerST.h      2011-11-08 12:44:10 UTC (rev 4784)
@@ -23,6 +23,8 @@
 #ifndef __RFB_VNCSERVERST_H__
 #define __RFB_VNCSERVERST_H__
 
+#include <sys/time.h>
+
 #include <list>
 
 #include <rfb/SDesktop.h>
@@ -31,6 +33,7 @@
 #include <rfb/LogWriter.h>
 #include <rfb/Blacklist.h>
 #include <rfb/Cursor.h>
+#include <rfb/Timer.h>
 #include <network/Socket.h>
 #include <rfb/ListConnInfo.h>
 #include <rfb/ScreenSet.h>
@@ -42,7 +45,9 @@
   class PixelBuffer;
   class KeyRemapper;
 
-  class VNCServerST : public VNCServer, public network::SocketServer {
+  class VNCServerST : public VNCServer,
+                      public Timer::Callback,
+                      public network::SocketServer {
   public:
     // -=- Constructors
 
@@ -85,7 +90,6 @@
     virtual void serverCutText(const char* str, int len);
     virtual void add_changed(const Region &region);
     virtual void add_copied(const Region &dest, const Point &delta);
-    virtual void tryUpdate();
     virtual void setCursor(int width, int height, const Point& hotspot,
                            void* cursorData, void* mask);
     virtual void setCursorPos(const Point& p);
@@ -192,6 +196,11 @@
 
     friend class VNCSConnectionST;
 
+    // Timer callbacks
+    virtual bool handleTimeout(Timer* t);
+
+    // - Internal methods
+
     void startDesktop();
 
     static LogWriter connectionsLog;
@@ -222,7 +231,10 @@
     int authClientCount();
 
     bool needRenderedCursor();
-    void checkUpdate();
+    void startDefer();
+    bool checkDefer();
+    void tryUpdate();
+    bool checkUpdate();
 
     void notifyScreenLayoutChange(VNCSConnectionST *requester);
 
@@ -235,6 +247,10 @@
     time_t lastConnectionTime;
 
     bool disableclients;
+
+    Timer deferTimer;
+    bool deferPending;
+    struct timeval deferStart;
   };
 
 };

Modified: trunk/unix/x0vncserver/PollingManager.cxx
===================================================================
--- trunk/unix/x0vncserver/PollingManager.cxx   2011-11-08 12:42:41 UTC (rev 
4783)
+++ trunk/unix/x0vncserver/PollingManager.cxx   2011-11-08 12:44:10 UTC (rev 
4784)
@@ -123,9 +123,7 @@
   debugBeforePoll();
 #endif
 
-  // Perform polling and try update clients if changes were detected.
-  if (pollScreen(server))
-    server->tryUpdate();
+  pollScreen(server);
 
 #ifdef DEBUG
   debugAfterPoll();

Modified: trunk/unix/xserver/hw/vnc/Input.cc
===================================================================
--- trunk/unix/xserver/hw/vnc/Input.cc  2011-11-08 12:42:41 UTC (rev 4783)
+++ trunk/unix/xserver/hw/vnc/Input.cc  2011-11-08 12:44:10 UTC (rev 4784)
@@ -207,7 +207,6 @@
 
        oldCursorPos = cursorPos;
        server->setCursorPos(cursorPos);
-       server->tryUpdate();
 }
 
 static int pointerProc(DeviceIntPtr pDevice, int onoff)

Modified: trunk/unix/xserver/hw/vnc/XserverDesktop.cc
===================================================================
--- trunk/unix/xserver/hw/vnc/XserverDesktop.cc 2011-11-08 12:42:41 UTC (rev 
4783)
+++ trunk/unix/xserver/hw/vnc/XserverDesktop.cc 2011-11-08 12:44:10 UTC (rev 
4784)
@@ -64,12 +64,6 @@
 
 static LogWriter vlog("XserverDesktop");
 
-rfb::IntParameter deferUpdateTime("DeferUpdate",
-                                  "Time in milliseconds to defer updates",1);
-
-rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer",
-                  "Always reset the defer update timer on every change",false);
-
 IntParameter queryConnectTimeout("QueryConnectTimeout",
                                  "Number of seconds to show the Accept 
Connection dialog before "
                                  "rejecting the connection",
@@ -145,7 +139,7 @@
                                network::TcpListener* httpListener_,
                                const char* name, const rfb::PixelFormat &pf,
                                void* fbptr, int stride)
-  : pScreen(pScreen_), deferredUpdateTimer(0),
+  : pScreen(pScreen_),
     server(0), httpServer(0),
     listener(listener_), httpListener(httpListener_),
     cmap(0), deferredUpdateTimerSet(false),
@@ -171,7 +165,6 @@
 {
   if (!directFbptr)
     delete [] data;
-  TimerFree(deferredUpdateTimer);
   delete inputDevice;
   delete httpServer;
   delete server;
@@ -441,7 +434,6 @@
     server->setCursor(cursor->bits->width, cursor->bits->height,
                       Point(cursor->bits->xhot, cursor->bits->yhot),
                       cursorData, cursorMask);
-    server->tryUpdate();
     delete [] cursorData;
     delete [] cursorMask;
   } catch (rdr::Exception& e) {
@@ -449,33 +441,6 @@
   }
 }
 
-CARD32 XserverDesktop::deferredUpdateTimerCallback(OsTimerPtr timer,
-                                                   CARD32 now, pointer arg)
-{
-  XserverDesktop* desktop = (XserverDesktop*)arg;
-  desktop->deferredUpdateTimerSet = false;
-  try {
-    desktop->server->tryUpdate();
-  } catch (rdr::Exception& e) {
-    vlog.error("XserverDesktop::deferredUpdateTimerCallback: %s",e.str());
-  }
-  return 0;
-}
-
-void XserverDesktop::deferUpdate()
-{
-  if (deferUpdateTime != 0) {
-    if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
-      deferredUpdateTimerSet = true;
-      deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
-                                     deferUpdateTime,
-                                     deferredUpdateTimerCallback, this);
-    }
-  } else {
-    server->tryUpdate();
-  }
-}
-
 void XserverDesktop::add_changed(RegionPtr reg)
 {
   if (ignoreHooks_) return;
@@ -486,7 +451,6 @@
                                      REGION_NUM_RECTS(reg),
                                      (ShortRect*)REGION_RECTS(reg));
     server->add_changed(rfbReg);
-    deferUpdate();
   } catch (rdr::Exception& e) {
     vlog.error("XserverDesktop::add_changed: %s",e.str());
   }
@@ -502,7 +466,6 @@
                                      REGION_NUM_RECTS(dst),
                                      (ShortRect*)REGION_RECTS(dst));
     server->add_copied(rfbReg, rfb::Point(dx, dy));
-    deferUpdate();
   } catch (rdr::Exception& e) {
     vlog.error("XserverDesktop::add_copied: %s",e.str());
   }

Modified: trunk/unix/xserver/hw/vnc/XserverDesktop.h
===================================================================
--- trunk/unix/xserver/hw/vnc/XserverDesktop.h  2011-11-08 12:42:41 UTC (rev 
4783)
+++ trunk/unix/xserver/hw/vnc/XserverDesktop.h  2011-11-08 12:44:10 UTC (rev 
4784)
@@ -121,12 +121,8 @@
 
 private:
   void setColourMapEntries(int firstColour, int nColours);
-  static CARD32 deferredUpdateTimerCallback(OsTimerPtr timer, CARD32 now,
-                                            pointer arg);
-  void deferUpdate();
   ScreenPtr pScreen;
   InputDevice *inputDevice;
-  OsTimerPtr deferredUpdateTimer;
   rfb::VNCServerST* server;
   rfb::HTTPServer* httpServer;
   network::TcpListener* listener;

Modified: trunk/win/rfb_win32/SDisplay.cxx
===================================================================
--- trunk/win/rfb_win32/SDisplay.cxx    2011-11-08 12:42:41 UTC (rev 4783)
+++ trunk/win/rfb_win32/SDisplay.cxx    2011-11-08 12:44:10 UTC (rev 4784)
@@ -378,8 +378,6 @@
 
     // - Only process updates if the server is ready
     if (server) {
-      bool try_update = false;
-
       // - Check that the SDesktop doesn't need restarting
       if (isRestartRequired()) {
         restartCore();
@@ -411,16 +409,12 @@
         // NB: First translate from Screen coordinates to Desktop
         Point desktopPos = info.position.translate(screenRect.tl.negate());
         server->setCursorPos(desktopPos);
-        try_update = true;
 
         old_cursor = info;
       }
 
       // Flush any changes to the server
-      try_update = flushChangeTracker() || try_update;
-      if (try_update) {
-        server->tryUpdate();
-      }
+      flushChangeTracker();
     }
     return;
   }

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
Tigervnc-commits mailing list
Tigervnc-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tigervnc-commits

Reply via email to