Fix bug in Debug refresh lock that, with too much data to debug, flooded GUI and blocked it
authorLaurent Bessard
Sat, 03 Nov 2012 17:00:26 +0100
changeset 875 a8952b79caec
parent 874 8b24e9312f18
child 876 179d5c455f29
Fix bug in Debug refresh lock that, with too much data to debug, flooded GUI and blocked it
Beremiz.py
graphics/GraphicCommons.py
--- a/Beremiz.py	Wed Oct 31 12:05:44 2012 +0100
+++ b/Beremiz.py	Sat Nov 03 17:00:26 2012 +0100
@@ -211,9 +211,16 @@
             if current_time - self.LastRefreshTime > REFRESH_PERIOD and self.RefreshLock.acquire(False):
                 self._should_write()
             else:
-                self.LastRefreshTimer = Timer(REFRESH_PERIOD, self._should_write)
+                self.LastRefreshTimer = Timer(REFRESH_PERIOD, self._timer_expired)
                 self.LastRefreshTimer.start()
 
+    def _timer_expired(self):
+        if self.RefreshLock.acquire(False):
+            self._should_write()
+        else:
+            self.LastRefreshTimer = Timer(REFRESH_PERIOD, self._timer_expired)
+            self.LastRefreshTimer.start()
+
     def _should_write(self):
         wx.CallAfter(self._write)
         if MainThread == currentThread().ident:
@@ -225,7 +232,7 @@
 
     def _write(self):
         if self.output :
-            self.output.Freeze(); 
+            self.output.Freeze()
             self.lock.acquire()
             for s, style in self.stack:
                 if style is None : style=self.black_white
@@ -247,7 +254,7 @@
             if newtime - self.rising_timer > 1:
                 self.risecall()
             self.rising_timer = newtime
-
+        
     def write_warning(self, s):
         self.write(s,self.red_white)
 
--- a/graphics/GraphicCommons.py	Wed Oct 31 12:05:44 2012 +0100
+++ b/graphics/GraphicCommons.py	Sat Nov 03 17:00:26 2012 +0100
@@ -27,7 +27,7 @@
 from math import *
 from types import *
 import datetime
-from threading import Semaphore
+from threading import Lock,Timer
 
 #-------------------------------------------------------------------------------
 #                               Common constants
@@ -293,6 +293,7 @@
 #-------------------------------------------------------------------------------
 
 REFRESH_PERIOD = 0.1
+DEBUG_REFRESH_LOCK = Lock()
 
 class DebugViewer:
     
@@ -305,10 +306,10 @@
         self.DataConsumers = {}
         
         self.LastRefreshTime = gettime()
-        self.RefreshLock = Semaphore()
+        self.HasAcquiredLock = False
+        self.AccessLock = Lock()
         
-        self.RefreshTimer = wx.Timer(self, -1)
-        self.Bind(wx.EVT_TIMER, self.OnRefreshTimer, self.RefreshTimer)
+        self.LastRefreshTimer = None
         
         self.SetDataProducer(producer)
         
@@ -366,15 +367,26 @@
                 self.DataProducer.UnsubscribeDebugIECVariable(iec_path, consumer)
         self.DataConsumers = {}
     
-    def OnRefreshTimer(self, event):
-        self.RefreshNewData()
-        event.Skip()
+    def ShouldRefresh(self):
+        if DEBUG_REFRESH_LOCK.acquire(False):
+            self.AccessLock.acquire()
+            self.HasAcquiredLock = True
+            self.AccessLock.release()
+            self.RefreshNewData()
+        else:
+            self.LastRefreshTimer = Timer(REFRESH_PERIOD, self.ShouldRefresh)
+            self.LastRefreshTimer.start()
     
     def NewDataAvailable(self, *args, **kwargs):
-        self.RefreshTimer.Stop()
+        if self.LastRefreshTimer is not None:
+            self.LastRefreshTimer.cancel()
+            self.LastRefreshTimer=None
         if not self.Inhibited:
             current_time = gettime()
-            if current_time - self.LastRefreshTime > REFRESH_PERIOD and self.RefreshLock.acquire(False):
+            if current_time - self.LastRefreshTime > REFRESH_PERIOD and DEBUG_REFRESH_LOCK.acquire(False):
+                self.AccessLock.acquire()
+                self.HasAcquiredLock = True
+                self.AccessLock.release()
                 self.LastRefreshTime = gettime()
                 self.Inhibit(True)
                 wx.CallAfter(self.RefreshViewOnNewData, *args, **kwargs)
@@ -382,12 +394,17 @@
     def RefreshViewOnNewData(self, *args, **kwargs):
         if self:
             self.RefreshNewData(*args, **kwargs)
-            self.RefreshTimer.Start(int(REFRESH_PERIOD * 1000), oneShot=True)
+            self.LastRefreshTimer = Timer(REFRESH_PERIOD, self.ShouldRefresh)
+            self.LastRefreshTimer.start()
     
     def RefreshNewData(self, *args, **kwargs):
         self.Inhibit(False)
-        self.RefreshLock.release()
-        
+        self.AccessLock.acquire()
+        if self.HasAcquiredLock:
+            DEBUG_REFRESH_LOCK.release()
+            self.HasAcquiredLock = False
+        self.AccessLock.release()
+
 #-------------------------------------------------------------------------------
 #                               Viewer Rubberband
 #-------------------------------------------------------------------------------