octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Evaluate GUI/core link not working properly


From: Daniel J Sebald
Subject: Evaluate GUI/core link not working properly
Date: Mon, 12 Aug 2013 19:00:43 -0500
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.24) Gecko/20111108 Fedora/3.1.16-1.fc14 Thunderbird/3.1.16

In sprucing up the history window "Evaluate" feature I've noticed that evaluating a block of commands results in what looks like a random evaluation. Some of the commands are dropped, sometimes out of order, sometimes a mangling of two commands.

A bit of investigation has made me wonder if the queuing of commands is done properly. Here is how commands are placed in the "evaluate queue":

void
main_window::execute_command_in_terminal (const QString& command)
{
  octave_link::post_event (this, &main_window::execute_command_callback,
                           command.toStdString ());

  focus_command_window ();
}

As far as I can tell, this command via abstraction makes its way to the action_container class object called "event_queue", where the command is placed into a FIFO

  void add (elem *new_elem)
  {
    fifo.push (new_elem);
  }

The problem is that nowhere along the way is there any type of MutEx handshaking to ensure that the GUI process and the core (worker) process aren't manipulating the FIFO at the same time. My guess is that there's some type of conflict that is mangling pointers at the front and back of the FIFO.

Copying commands into the command line window doesn't seem to lose lines of text. Perhaps that is a different mechanism or has proper handshaking.

In some sense, it doesn't seem like any of the queuing of commands should be the responsibility of the core. I would think that the link is responsible for that, i.e., the feature should reside in the GUI specific octave_link. A while back I did a prototype that boiled down to this function that the GUI calls:

+void
+octave_qt_link::handle_queue_octave_command (const QString& command,
+                                             const int nargout)
+{
+  background_queue_mutex.lock ();
+  command_info cominf = {sender (), command, nargout};
+  background_octave_command_queue.append (cominf);
+  background_queue_mutex.unlock ();
+}

and the following function that the core calls:

+
+void
+octave_qt_link::do_process_events (void)
+{
+  while (! background_octave_command_queue.isEmpty ())
+    {
+      background_queue_mutex.lock ();
+      command_info ci = background_octave_command_queue.takeFirst ();
+      background_queue_mutex.unlock ();
+
+      // Evaluate this string without producing any output or advancing the
+      // line number shown at the terminal command line prompt.
+      octave_value_list retval;
+      int parse_status;
+      retval = eval_string (ci.command.toStdString (), false,
+                            parse_status, ci.nargout);
+
+      int command_status;
+      if (parse_status)
+        command_status = ParseFail;
+      else if (error_state)
+        command_status = ProcessFail;
+      else
+        command_status = CommandOK;
+
+      // This lock is to ensure that this Octave worker thread becomes
+      // unlocked by the QWaitCondition a few lines further down before
+      // the GUI thread attempts to wake the process.  Otherwise, there
+      // is the risk of this thread being awaken before going to sleep.
+      events_process_mutex.lock ();
+
+      emit transmit_octave_command_result (ci.senderid, ci.command,
+                                           command_status, retval);
+
+      events_process_waitcondition.wait (&events_process_mutex);
+      events_process_mutex.unlock ();
+    }
+}

The bottom line is that somewhere mutex.lock() / mutex.unlock() has to be done. It could either be the GUI's mechanism or the core's mechanism, I suppose, but to me it feels like the GUI is the best place for this at least with the way Qt graphics/worker processes are currently set up, and probably more generally as well.

Dan


reply via email to

[Prev in Thread] Current Thread [Next in Thread]