From d8bb21fe782b6c8e485c29a8130e71c07c32ca8e Mon Sep 17 00:00:00 2001
From: Julien Malik <julien.malik@c-s.fr>
Date: Mon, 21 Mar 2011 10:28:49 +0100
Subject: [PATCH] ENH: protect progress watchers against flooding

If the underlying filter sends a lot of ProgressEvent, the current watchers implementation triggered
a visualisation update at each ProgressEvent, thus reducing overall performance
---
 Code/Common/otbFilterWatcherBase.cxx     | 18 +++---
 Code/Common/otbFilterWatcherBase.h       | 18 ++++++
 Code/Common/otbStandardFilterWatcher.cxx | 12 +++-
 Code/Common/otbStandardFilterWatcher.h   |  2 +
 Code/Gui/otbFltkFilterWatcher.cxx        | 38 +++++++++++-
 Code/Gui/otbFltkFilterWatcher.h          | 31 +++-------
 Code/Gui/otbFltkWriterWatcher.cxx        | 78 +++++++++++++++++++++++-
 Code/Gui/otbFltkWriterWatcher.h          | 64 ++++++-------------
 8 files changed, 177 insertions(+), 84 deletions(-)

diff --git a/Code/Common/otbFilterWatcherBase.cxx b/Code/Common/otbFilterWatcherBase.cxx
index 2e47d89fc3..742eb90d37 100644
--- a/Code/Common/otbFilterWatcherBase.cxx
+++ b/Code/Common/otbFilterWatcherBase.cxx
@@ -46,11 +46,11 @@ FilterWatcherBase
 
   // Assign the callbacks
   m_StartFilterCommand->SetCallbackFunction(this,
-                                            &FilterWatcherBase::StartFilter);
+                                            &FilterWatcherBase::StartFilterCallback);
   m_EndFilterCommand->SetCallbackFunction(this,
-                                          &FilterWatcherBase::EndFilter);
+                                          &FilterWatcherBase::EndFilterCallback);
   m_ProgressFilterCommand->SetCallbackFunction(this,
-                                               &FilterWatcherBase::ShowProgress);
+                                               &FilterWatcherBase::ShowProgressCallback);
 
   // Add the commands as observers
   m_StartTag = m_Process->AddObserver(itk::StartEvent(),
@@ -90,11 +90,11 @@ FilterWatcherBase
 
     // Assign the callbacks
     m_StartFilterCommand->SetCallbackFunction(this,
-                                              &FilterWatcherBase::StartFilter);
+                                              &FilterWatcherBase::StartFilterCallback);
     m_EndFilterCommand->SetCallbackFunction(this,
-                                            &FilterWatcherBase::EndFilter);
+                                            &FilterWatcherBase::EndFilterCallback);
     m_ProgressFilterCommand->SetCallbackFunction(this,
-                                                 &FilterWatcherBase::ShowProgress);
+                                                 &FilterWatcherBase::ShowProgressCallback);
 
     // Add the commands as observers
     m_StartTag = m_Process->AddObserver(itk::StartEvent(), m_StartFilterCommand);
@@ -132,11 +132,11 @@ FilterWatcherBase
 
     // Assign the callbacks
     m_StartFilterCommand->SetCallbackFunction(this,
-                                              &FilterWatcherBase::StartFilter);
+                                              &FilterWatcherBase::StartFilterCallback);
     m_EndFilterCommand->SetCallbackFunction(this,
-                                            &FilterWatcherBase::EndFilter);
+                                            &FilterWatcherBase::EndFilterCallback);
     m_ProgressFilterCommand->SetCallbackFunction(this,
-                                                 &FilterWatcherBase::ShowProgress);
+                                                 &FilterWatcherBase::ShowProgressCallback);
 
     // Add the commands as observers
     m_StartTag = m_Process->AddObserver(itk::StartEvent(), m_StartFilterCommand);
diff --git a/Code/Common/otbFilterWatcherBase.h b/Code/Common/otbFilterWatcherBase.h
index 9e64c17632..ef739e490c 100644
--- a/Code/Common/otbFilterWatcherBase.h
+++ b/Code/Common/otbFilterWatcherBase.h
@@ -85,6 +85,24 @@ public:
 
 protected:
 
+  /** Callback method to show the ProgressEvent */
+  virtual void ShowProgressCallback()
+  {
+    this->ShowProgress();
+  }
+
+  /** Callback method to show the StartEvent */
+  virtual void StartFilterCallback()
+  {
+    this->StartFilter();
+  }
+
+  /** Callback method to show the EndEvent */
+  virtual void EndFilterCallback()
+  {
+    this->EndFilter();
+  }
+
   /** Callback method to show the ProgressEvent */
   virtual void ShowProgress() = 0;
 
diff --git a/Code/Common/otbStandardFilterWatcher.cxx b/Code/Common/otbStandardFilterWatcher.cxx
index 1fd3e7d4dc..ce47e316a5 100644
--- a/Code/Common/otbStandardFilterWatcher.cxx
+++ b/Code/Common/otbStandardFilterWatcher.cxx
@@ -29,6 +29,7 @@ StandardFilterWatcher
   : FilterWatcherBase(process, comment)
 {
   m_StarsCount = 50;
+  m_CurrentNbStars = -1;
 }
 
 StandardFilterWatcher
@@ -80,9 +81,14 @@ StandardFilterWatcher
       progressPercent = 100;
       }
 
-    std::string stars(nbStars, '*');
-    std::string blanks(nbBlanks, ' ');
-    std::cout << "\rProcessing progress: " << progressPercent << "% [" << stars << blanks << "]" << std::flush;
+    if (nbStars > m_CurrentNbStars)
+      {
+      std::string stars(nbStars, '*');
+      std::string blanks(nbBlanks, ' ');
+      std::cout << "\rProcessing progress: " << progressPercent << "% [" << stars << blanks << "]" << std::flush;
+      }
+
+    m_CurrentNbStars = nbStars;
     }
 }
 
diff --git a/Code/Common/otbStandardFilterWatcher.h b/Code/Common/otbStandardFilterWatcher.h
index 1f3cbe6e91..5e4fd7f690 100644
--- a/Code/Common/otbStandardFilterWatcher.h
+++ b/Code/Common/otbStandardFilterWatcher.h
@@ -92,6 +92,8 @@ private:
 
   /** Stars coutning */
   int m_StarsCount;
+
+  int m_CurrentNbStars;
 };
 
 } // end namespace otb
diff --git a/Code/Gui/otbFltkFilterWatcher.cxx b/Code/Gui/otbFltkFilterWatcher.cxx
index 65ef6e5452..8136428c44 100644
--- a/Code/Gui/otbFltkFilterWatcher.cxx
+++ b/Code/Gui/otbFltkFilterWatcher.cxx
@@ -27,7 +27,8 @@ FltkFilterWatcher
 ::FltkFilterWatcher(itk::ProcessObject* process,
                     int x, int y, int w, int h,
                     const char *comment)
-  : FilterWatcherBase(process, comment)
+  : FilterWatcherBase(process, comment),
+    m_CurrentProgress(0)
 {
   m_Window = new Fl_Window(x, y, w + 10, h + 10);
   m_Window->label(m_Comment.c_str());
@@ -46,4 +47,39 @@ FltkFilterWatcher
   delete m_Window;
 }
 
+void
+FltkFilterWatcher
+::StartFilter()
+{
+  m_Window->show();
+  m_Progress->value(0);
+  m_Progress->show();
+  Fl::check();
+}
+
+void
+FltkFilterWatcher
+::ShowProgress()
+{
+  if (m_Process)
+    {
+    double progress = m_Process->GetProgress();
+
+    // Update only at each 0.5 percent
+    if (progress - m_CurrentProgress > 0.005)
+      {
+      m_Progress->value(progress);
+      m_CurrentProgress = progress;
+      Fl::check();
+      }
+    }
+}
+
+void
+FltkFilterWatcher
+::EndFilter()
+{
+  m_Window->hide();
+}
+
 } // end namespace otb
diff --git a/Code/Gui/otbFltkFilterWatcher.h b/Code/Gui/otbFltkFilterWatcher.h
index f15a47bcf4..c8bc02ce51 100644
--- a/Code/Gui/otbFltkFilterWatcher.h
+++ b/Code/Gui/otbFltkFilterWatcher.h
@@ -38,9 +38,6 @@ namespace otb
 class ITK_EXPORT FltkFilterWatcher : public FilterWatcherBase
 {
 public:
-  /** Classes that need access to filter's private data */
-  // friend class XMLFilterWatcher;
-
   /** Constructor. Takes a ProcessObject to monitor and an optional
    * comment string that is prepended to each event message. */
   FltkFilterWatcher(itk::ProcessObject * process,
@@ -50,35 +47,21 @@ public:
   /** Destructor. */
   virtual ~FltkFilterWatcher();
 
-  /** Callback method to show the EndEvent */
-  virtual void EndFilter()
-  {
-    m_Window->hide();
-  }
-
 protected:
-
   /** Callback method to show the ProgressEvent */
-  virtual void ShowProgress()
-  {
-    if (m_Process)
-      {
-      m_Progress->value(m_Process->GetProgress());
-      Fl::check();
-      }
-  }
+  virtual void ShowProgress();
 
   /** Callback method to show the StartEvent */
-  virtual void StartFilter()
-  {
-    m_Window->show();
-    m_Progress->show();
-  }
+  virtual void StartFilter();
 
-private:
+  /** Callback method to show the EndEvent */
+  virtual void EndFilter();
 
+private:
   Fl_Window *   m_Window;
   Fl_Progress * m_Progress;
+
+  double m_CurrentProgress;
 };
 
 } // end namespace otb
diff --git a/Code/Gui/otbFltkWriterWatcher.cxx b/Code/Gui/otbFltkWriterWatcher.cxx
index a3779c4ba2..b99700274f 100644
--- a/Code/Gui/otbFltkWriterWatcher.cxx
+++ b/Code/Gui/otbFltkWriterWatcher.cxx
@@ -27,7 +27,9 @@ FltkWriterWatcher
 ::FltkWriterWatcher(itk::ProcessObject* process,
                     int x, int y, int w, int h,
                     const char *comment)
-  : WriterWatcherBase(process, comment)
+  : WriterWatcherBase(process, comment),
+    m_CurrentFilterProgress(0),
+    m_CurrentWriterProgress(0)
 {
   this->BuildGUI(x, y, w, h, comment);
 }
@@ -37,7 +39,9 @@ FltkWriterWatcher
                     itk::ProcessObject* source,
                     int x, int y, int w, int h,
                     const char *comment)
-  : WriterWatcherBase(process, source, comment)
+  : WriterWatcherBase(process, source, comment),
+    m_CurrentFilterProgress(0),
+    m_CurrentWriterProgress(0)
 {
   this->BuildGUI(x, y, w, h, comment);
 }
@@ -78,4 +82,74 @@ FltkWriterWatcher
   delete m_Window;
 }
 
+
+void
+FltkWriterWatcher
+::StartFilter()
+{
+  m_Window->show();
+  m_FilterProgress->show();
+  m_WriterProgress->show();
+  Fl::check();
+}
+
+void
+FltkWriterWatcher
+::ShowFilterProgress()
+{
+  if (m_SourceProcess)
+    {
+    double progress = m_SourceProcess->GetProgress();
+
+    // Update only at each 0.5 percent
+    if (progress - m_CurrentFilterProgress > 0.005)
+      {
+      m_FilterProgress->value(progress);
+      m_CurrentFilterProgress = progress;
+      Fl::check();
+      }
+    }
+}
+
+void
+FltkWriterWatcher
+::EndFilter()
+{
+}
+
+void
+FltkWriterWatcher
+::StartWriter()
+{
+  m_Window->show();
+  m_FilterProgress->show();
+  m_WriterProgress->show();
+  Fl::check();
+}
+
+void
+FltkWriterWatcher
+::ShowWriterProgress()
+{
+  if (m_Process)
+    {
+    double progress = m_Process->GetProgress();
+
+    // Update only at each 0.5 percent
+    if (progress - m_CurrentWriterProgress > 0.005)
+      {
+      m_WriterProgress->value(progress);
+      m_CurrentWriterProgress = progress;
+      Fl::check();
+      }
+    }
+}
+
+void
+FltkWriterWatcher
+::EndWriter()
+{
+  m_Window->hide();
+}
+
 } // end namespace otb
diff --git a/Code/Gui/otbFltkWriterWatcher.h b/Code/Gui/otbFltkWriterWatcher.h
index e03ecd03f0..224d69a6ea 100644
--- a/Code/Gui/otbFltkWriterWatcher.h
+++ b/Code/Gui/otbFltkWriterWatcher.h
@@ -55,54 +55,25 @@ public:
   /** Destructor. */
   virtual ~FltkWriterWatcher();
 
-  /** Callback method to show the EndEvent */
-  virtual void EndWriter()
-  {
-    m_Window->hide();
-  }
+protected:
 
-  virtual void EndFilter()
-  {}
+  /** Callback method to show the ProgressEvent from the writer */
+  virtual void ShowWriterProgress();
 
-protected:
+  /** Callback method to show the StartEvent from the writer*/
+  virtual void StartWriter();
+
+  /** Callback method to show the EndEvent from the writer*/
+  virtual void EndWriter();
 
-  /** Callback method to show the ProgressEvent */
-  virtual void ShowFilterProgress()
-  {
-    if (m_SourceProcess)
-      {
-      m_FilterProgress->value(m_SourceProcess->GetProgress());
-      Fl::check();
-      }
-  }
-
-  /** Callback method to show the ProgressEvent */
-  virtual void ShowWriterProgress()
-  {
-    if (m_Process)
-      {
-      m_WriterProgress->value(m_Process->GetProgress());
-      Fl::check();
-      }
-  }
-
-  /** Callback method to show the StartEvent */
-  virtual void StartWriter()
-  {
-    m_Window->show();
-    m_FilterProgress->show();
-    m_WriterProgress->show();
-    Fl::check();
-  }
-
-  /** Callback method to show the StartEvent */
-  virtual void StartFilter()
-  {
-    m_Window->show();
-    m_FilterProgress->show();
-    m_WriterProgress->show();
-    Fl::check();
-  }
+  /** Callback method to show the ProgressEvent from the filter */
+  virtual void ShowFilterProgress();
+
+  /** Callback method to show the StartEvent from the filter*/
+  virtual void StartFilter();
+
+  /** Callback method to show the EndEvent from the filter*/
+  virtual void EndFilter();
 
   void BuildGUI(int x, int y, int w, int h, const char * comment);
 
@@ -111,6 +82,9 @@ private:
   Fl_Window *   m_Window;
   Fl_Progress * m_WriterProgress;
   Fl_Progress * m_FilterProgress;
+
+  double m_CurrentFilterProgress;
+  double m_CurrentWriterProgress;
 };
 
 } // end namespace otb
-- 
GitLab