changeset 18250:0da2e7051778 stable

synchronize gui's debug actions with the octave core thread (bug #41139) * main-window.cc (constructor): initialize new queue with debug commands (debug_continue, debug_step_into, debug_step_over, debug_step_out, debug_quit): call queue_debug instead post octave_link-event and remove the related callback functions (queue_debug): new functin handling the queue of debug actions and posting octave_link events; (execute_debug_callback): common new callback function for debug actions * main-window.h: removed functions: debug_continue_callback, debug_step_into_callback, debug_step_over_callback, debug_step_out_callback, debug_quit_callback; new functions: queue_debug, execute_debug_callback; new variables for handling the debug queue
author Torsten <ttl@justmail.de>
date Wed, 08 Jan 2014 21:50:45 +0100
parents 8193ef6d07fc
children 0b5f669f5b03
files libgui/src/main-window.cc libgui/src/main-window.h
diffstat 2 files changed, 55 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/main-window.cc	Thu Jan 09 07:58:09 2014 -0800
+++ b/libgui/src/main-window.cc	Wed Jan 08 21:50:45 2014 +0100
@@ -88,7 +88,10 @@
     _clipboard (QApplication::clipboard ()),
     _cmd_queue (new QStringList ()),  // no command pending
     _cmd_processing (1),
-    _cmd_queue_mutex ()
+    _cmd_queue_mutex (),
+    _dbg_queue (new QStringList ()),  // no debug pending
+    _dbg_processing (1),
+    _dbg_queue_mutex ()
 {
   QSettings *settings = resource_manager::get_settings ();
 
@@ -770,31 +773,31 @@
 void
 main_window::debug_continue (void)
 {
-  octave_link::post_event (this, &main_window::debug_continue_callback);
+  queue_debug ("cont");
 }
 
 void
 main_window::debug_step_into (void)
 {
-  octave_link::post_event (this, &main_window::debug_step_into_callback);
+  queue_debug ("in");
 }
 
 void
 main_window::debug_step_over (void)
 {
-  octave_link::post_event (this, &main_window::debug_step_over_callback);
+  queue_debug ("step");
 }
 
 void
 main_window::debug_step_out (void)
 {
-  octave_link::post_event (this, &main_window::debug_step_out_callback);
+  queue_debug ("out");
 }
 
 void
 main_window::debug_quit (void)
 {
-  octave_link::post_event (this, &main_window::debug_quit_callback);
+  queue_debug ("quit");
 }
 
 void
@@ -2091,15 +2094,7 @@
   Fcd (ovl (directory));
 }
 
-void
-main_window::debug_continue_callback (void)
-{
-  Fdbcont ();
-
-  command_editor::interrupt (true);
-}
-
-// The next three callbacks are invoked by GUI buttons.  Those buttons
+// The next callbacks are invoked by GUI buttons.  Those buttons
 // should only be active when we are doing debugging, which means that
 // Octave is waiting for input in get_debug_input.  Calling
 // command_editor::interrupt will force readline to return even if it
@@ -2107,35 +2102,46 @@
 // allowing the evaluator to continue and execute the next statement.
 
 void
-main_window::debug_step_into_callback (void)
+main_window::queue_debug (QString debug_cmd)
 {
-  Fdbstep (ovl ("in"));
-
-  command_editor::interrupt (true);
+  _dbg_queue_mutex.lock ();
+  _dbg_queue->append (debug_cmd);   // queue command
+  _dbg_queue_mutex.unlock ();
+
+  if (_dbg_processing.tryAcquire ())  // if callback not processing, post event
+    octave_link::post_event (this, &main_window::execute_debug_callback);
 }
 
 void
-main_window::debug_step_over_callback (void)
-{
-  Fdbstep ();
-
-  command_editor::interrupt (true);
-}
-
-void
-main_window::debug_step_out_callback (void)
+main_window::execute_debug_callback ()
 {
-  Fdbstep (ovl ("out"));
-
-  command_editor::interrupt (true);
-}
-
-void
-main_window::debug_quit_callback (void)
-{
-  Fdbquit ();
-
-  command_editor::interrupt (true);
+  bool repost = false;          // flag for reposting event for this callback
+
+  if (!_dbg_queue->isEmpty ())  // list can not be empty here, just to make sure
+    {
+      _dbg_queue_mutex.lock (); // critical path
+      QString debug = _dbg_queue->takeFirst ();
+      if (_dbg_queue->isEmpty ())
+        _dbg_processing.release ();  // cmd queue empty, processing will stop
+      else
+        repost = true;          // not empty, repost at end
+      _dbg_queue_mutex.unlock ();
+
+      if (debug == "step")
+        Fdbstep ();
+      else if (debug == "cont")
+        Fdbcont ();
+      else if (debug == "quit")
+        Fdbquit ();
+      else
+        Fdbstep (ovl (debug.toStdString ()));
+
+      command_editor::interrupt (true);
+    }
+
+  if (repost)  // queue not empty, so repost event for further processing
+    octave_link::post_event (this, &main_window::execute_debug_callback);
+
 }
 
 void
--- a/libgui/src/main-window.h	Thu Jan 09 07:58:09 2014 -0800
+++ b/libgui/src/main-window.h	Wed Jan 08 21:50:45 2014 +0100
@@ -255,19 +255,13 @@
 
   void change_directory_callback (const std::string& directory);
 
-  void debug_continue_callback (void);
-
-  void debug_step_into_callback (void);
-
-  void debug_step_over_callback (void);
-
-  void debug_step_out_callback (void);
-
-  void debug_quit_callback (void);
-
   void exit_callback (void);
 
-  void queue_command (QString command);  // Data models.
+  void queue_command (QString command);
+
+  void queue_debug (QString command);
+
+  void execute_debug_callback ();
 
   workspace_model *_workspace_model;
 
@@ -348,6 +342,11 @@
   QStringList *_cmd_queue;
   QSemaphore   _cmd_processing;
   QMutex       _cmd_queue_mutex;
+
+  // semaphore to synchronize debug signals and related callbacks
+  QStringList *_dbg_queue;
+  QSemaphore   _dbg_processing;
+  QMutex       _dbg_queue_mutex;
 };
 
 class news_reader : public QObject