changeset 17329:352b442a72a5

queue and synchronize mutliple commands executed fro history (bug #39723) * main-window.cc(constructor): Initialization of new class variables for the command queue, its mutex and a counting semaphore for handling the queue; (destructor): delete command queue; (execute_command_in_terinal): only call new function for queuing the command; (run_file_in_terminal): checking the path and building the cresulting ommand is done here and not in the callback, the command is finally queued (queue_command): new function for queuing commands and posteing the event for the execution callback if the callback is not already active; (execute_command_callback): no parameter because working on the command queue, reposting own event if the queue si not empty, releasing a semaphore if empty; (run_file_callback): removed, code is in run_file_in_terminal now * main-window.h: execute_command_callback without parameters, new function queue_command, new variables for the command queue, its mutex and for a semaphore handling the queue
author Torsten <ttl@justmail.de>
date Sat, 24 Aug 2013 23:29:42 +0200
parents 4daf633100db
children 219552139c18
files libgui/src/main-window.cc libgui/src/main-window.h
diffstat 2 files changed, 56 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/main-window.cc	Sat Aug 24 14:47:13 2013 -0400
+++ b/libgui/src/main-window.cc	Sat Aug 24 23:29:42 2013 +0200
@@ -78,7 +78,10 @@
     find_files_dlg (0),
     _octave_main_thread (0),
     _octave_qt_link (0),
-    _clipboard (QApplication::clipboard ())
+    _clipboard (QApplication::clipboard ()),
+    _cmd_queue (new QStringList ()),  // no command pending
+    _cmd_processing (1),
+    _cmd_queue_mutex ()
 {
   // We have to set up all our windows, before we finally launch octave.
   construct ();
@@ -104,6 +107,7 @@
     }
   delete _octave_main_thread;
   delete _octave_qt_link;
+  delete _cmd_queue;
 }
 
 bool
@@ -198,16 +202,30 @@
 void
 main_window::execute_command_in_terminal (const QString& command)
 {
-  octave_link::post_event (this, &main_window::execute_command_callback,
-                           command.toStdString ());
-
+  queue_command (command);
   focus_command_window ();
 }
 
 void
 main_window::run_file_in_terminal (const QFileInfo& info)
 {
-  octave_link::post_event (this, &main_window::run_file_callback, info);
+  QString dir = info.absolutePath ();
+  QString function_name = info.fileName ();
+  function_name.chop (info.suffix ().length () + 1);
+  if (octave_qt_link::file_in_path (info.absoluteFilePath ().toStdString (),
+                                    dir.toStdString ()))
+    queue_command (function_name);
+}
+
+void
+main_window::queue_command (QString command)
+{
+  _cmd_queue_mutex.lock ();
+  _cmd_queue->append (command);   // queue command
+  _cmd_queue_mutex.unlock ();
+
+  if (_cmd_processing.tryAcquire ())   // if callback is not processing, post event
+    octave_link::post_event (this, &main_window::execute_command_callback);
 }
 
 void
@@ -1482,29 +1500,34 @@
 }
 
 void
-main_window::execute_command_callback (const std::string& command)
+main_window::execute_command_callback ()
 {
-  std::string pending_input = command_editor::get_current_line ();
+  bool repost = false;          // flag for reposting event for this callback
 
-  command_editor::set_initial_input (pending_input);
-
-  command_editor::replace_line (command);
-  command_editor::redisplay ();
+  if (!_cmd_queue->isEmpty ())  // list can not be empty here, just to make sure
+    {
+      std::string pending_input = command_editor::get_current_line ();
+      command_editor::set_initial_input (pending_input);
 
-  // We are executing inside the command editor event loop.  Force
-  // the current line to be returned for processing.
-  command_editor::interrupt ();
-}
+      _cmd_queue_mutex.lock (); // critical path
+      std::string command = _cmd_queue->takeFirst ().toStdString ();
+      if (_cmd_queue->isEmpty ())
+        _cmd_processing.release ();  // command queue empty, processing will stop
+      else
+        repost = true;          // not empty, repost at end
+      _cmd_queue_mutex.unlock ();
+
+      command_editor::replace_line (command);
 
-void
-main_window::run_file_callback (const QFileInfo& info)
-{
-  QString dir = info.absolutePath ();
-  QString function_name = info.fileName ();
-  function_name.chop (info.suffix ().length () + 1);
-  if (octave_qt_link::file_in_path (info.absoluteFilePath ().toStdString (),
-                                    dir.toStdString ()))
-    execute_command_callback (function_name.toStdString ());
+      command_editor::redisplay ();
+      // We are executing inside the command editor event loop.  Force
+      // the current line to be returned for processing.
+      command_editor::interrupt ();
+    }
+
+  if (repost)  // queue not empty, so repost event for further processing
+    octave_link::post_event (this, &main_window::execute_command_callback);
+
 }
 
 void
--- a/libgui/src/main-window.h	Sat Aug 24 14:47:13 2013 -0400
+++ b/libgui/src/main-window.h	Sat Aug 24 23:29:42 2013 +0200
@@ -36,6 +36,7 @@
 #include <QCloseEvent>
 #include <QToolButton>
 #include <QComboBox>
+#include <QSemaphore>
 
 // Editor includes
 #include "file-editor-interface.h"
@@ -233,7 +234,7 @@
 
   void clear_history_callback (void);
 
-  void execute_command_callback (const std::string& command);
+  void execute_command_callback ();
   void run_file_callback (const QFileInfo& info);
 
   void new_figure_callback (void);
@@ -252,7 +253,8 @@
 
   void exit_callback (void);
 
-  // Data models.
+  void queue_command (QString command);  // Data models.
+
   workspace_model *_workspace_model;
 
   // Toolbars.
@@ -317,6 +319,11 @@
 
   // Flag for closing whole application.
   bool _closing;
+
+  // semaphore to synchronize execution signals and related callback
+  QStringList *_cmd_queue;
+  QSemaphore   _cmd_processing;
+  QMutex       _cmd_queue_mutex;
 };
 
 #endif // MAINWINDOW_H