changeset 13479:37d12b4531c5

Fetching the history was not thread-safe, now it is through encapsulation with OctaveLink.
author Jacob Dawid <jacob.dawid@googlemail.com>
date Thu, 21 Apr 2011 12:53:02 +0200
parents a51ad78b51c5
children daa94255fff1
files gui//src/MainWindow.h gui//src/OctaveLink.cpp gui//src/OctaveLink.h
diffstat 3 files changed, 51 insertions(+), 511 deletions(-) [+]
line wrap: on
line diff
--- a/gui//src/MainWindow.h
+++ b/gui//src/MainWindow.h
@@ -167,17 +167,8 @@
             m_mainWindow->variablesDockWidget()->setVariablesList(symbolTable);
         }
 
-        // Check whether any requested variables have been returned.
-        QList<OctaveLink::RequestedVariable> reqVars
-                = OctaveLink::instance()->requestedVariables();
-
-        //for(std::vector<OctaveLink::RequestedVariable>::iterator it = reqVars.begin();
-        //   it != reqVars.end(); it++ ) {
-            // TODO: Process requested variables.
-        //}
-
         // Collect history list.
-        string_vector historyList = OctaveLink::instance()->getHistoryList();
+        string_vector historyList = OctaveLink::instance()->currentHistory();
         if(historyList.length()) {
             m_mainWindow->historyDockWidget()->updateHistory(historyList);
         }
--- a/gui//src/OctaveLink.cpp
+++ b/gui//src/OctaveLink.cpp
@@ -25,29 +25,18 @@
 
 OctaveLink OctaveLink::m_singleton;
 
-static octave_user_code *
-get_user_code (const std::string& fname = std::string ())
-{
-  octave_user_code *dbg_fcn = 0;
 
-  if (fname.empty ())
-    dbg_fcn = octave_call_stack::caller_user_code ();
-  else
-    {
-      octave_value fcn = symbol_table::find_function (fname);
-
-      if (fcn.is_defined () && fcn.is_user_code ())
-	dbg_fcn = fcn.user_code_value ();
-    }
-
-  return dbg_fcn;
+OctaveLink::OctaveLink()
+    : QObject(),
+      m_previousHistoryLength(0) {
+    m_symbolTableSemaphore = new QSemaphore(1);
+    m_historySemaphore = new QSemaphore(1);
 }
 
-//*************************************************************************
+OctaveLink::~OctaveLink() {
+}
+
 int OctaveLink::readlineEventHook() {
-  // TODO: No need to run too quickly.  The documentation says it will run
-  // at most 10 times per second.  This may be too fast and we will need to
-  // artificially slow it down somehow.  Not sure at this time how.
   OctaveLink::instance()->processOctaveServerData();
   return 0;
 }
@@ -81,16 +70,6 @@
     }
 }
 
-//*************************************************************************
-OctaveLink::OctaveLink()
-    : QObject(),
-      m_previousHistoryLength(0) {
-    m_symbolTableSemaphore = new QSemaphore(1);
-}
-
-OctaveLink::~OctaveLink() {
-}
-
 void OctaveLink::fetchSymbolTable() {
     m_symbolTableSemaphore->acquire();
     m_symbolTableBuffer.clear();
@@ -99,6 +78,21 @@
     for(iterator = allVariables.begin(); iterator != allVariables.end(); iterator++)
         m_symbolTableBuffer.append(*iterator);
     m_symbolTableSemaphore->release();
+    emit symbolTableChanged();
+}
+
+
+void OctaveLink::fetchHistory() {
+    int currentLen = command_history::length();
+    if(currentLen != m_previousHistoryLength) {
+        m_historySemaphore->acquire();
+        for(int i = m_previousHistoryLength; i < currentLen; i++) {
+            m_historyBuffer.append(command_history::get_entry(i));
+        }
+        m_historySemaphore->release();
+        m_previousHistoryLength = currentLen;
+        emit historyChanged();
+    }
 }
 
 QList<SymbolRecord> OctaveLink::currentSymbolTable() {
@@ -113,348 +107,16 @@
     return m_symbolTableCopy;
 }
 
-
-//*************************************************************************
-QList<OctaveLink::RequestedVariable> OctaveLink::requestedVariables() {
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-    return m_requestedVariables;
-}
-
-//*************************************************************************
-int OctaveLink::setRequestedVariableNames(QList<QString> variablesNames) {
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-    m_variablesRequestList = variablesNames;
-    return 0;
-}
-
-//*************************************************************************
-string_vector OctaveLink::getHistoryList(void)
-{
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-
-    // Copy the list of command history items
-    string_vector retval( m_historyList );
-    m_historyList = string_vector();
-
-    return retval;
-}
-
-std::vector<OctaveLink::BreakPoint> OctaveLink::breakPointList(int& status)
-{
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-
-    // Copy the list of variable information
-    std::vector<BreakPoint> retval (m_currentBreakpoints.size());
-    std::copy( m_currentBreakpoints.begin(), m_currentBreakpoints.end(), retval.begin() );
-
-    status = 0;
-    return retval;
-}
-
-bool OctaveLink::isBreakpointReached()
-{
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-
-    // Copy the list of variable information
-    bool retval = (m_reachedBreakpoints.size()>0);
-    return retval;
-}
-
-std::vector<OctaveLink::BreakPoint> OctaveLink::reachedBreakpoint()
-{
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-
-    // Copy the list of variable information
-    std::vector<BreakPoint> retval (m_reachedBreakpoints.size());
-    std::copy (m_reachedBreakpoints.begin(), m_reachedBreakpoints.end(), retval.begin() );
-
+string_vector OctaveLink::currentHistory() {
+    m_historySemaphore->acquire();
+    string_vector retval(m_historyBuffer);
+    m_historyBuffer = string_vector();
+    m_historySemaphore->release();
     return retval;
 }
 
-int OctaveLink::addBreakpoint( BreakPoint bp_info )
-{
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-
-    // Copy the list of variable information
-    m_addedBreakpoints.push_back (bp_info);
-
-    return 0;
-}
-
-int OctaveLink::removeBreakpoint( BreakPoint bp_info )
-{
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-    // Copy the list of variable information
-    m_removedBreakpoints.push_back (bp_info);
-    return 0;
-}
-
-int OctaveLink::setBreakpointAction (BreakPointAction action)
-{
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-    m_breakPointAction = action;
-    return 0;
-}
-
-/*******************************************************************************
- *******************************************************************************
- * SERVER SIDE FUNCTIONS
- *******************************************************************************
- *******************************************************************************/
-
-//*************************************************************************
-int OctaveLink::processOctaveServerData(void) {
-    QMutexLocker mutexLocker(&m_internalAccessMutex);
-    process_breakpoint_action();
-    processBreakpointAndRemoveModify();
-    processRequestedVariables();
+void OctaveLink::processOctaveServerData() {
     fetchSymbolTable();
-    setHistoryList();
-    setBreakPointList();
-    return 0;
-}
-
-
-
-
-//*************************************************************************
-int OctaveLink::processRequestedVariables( void )
-{
-  /*
-
-  // Clear the list of existing requested variables
-  requested_variables = std::vector<requested_variable_t>();
-  
-  //// Get the list of variables and copy them into requested_variables vector
-  // XXX FIXME XXX Should separate argv to lists with and without dots.
-  if ( top_level_sym_tab != NULL )
-  {
-    if ( global_command == 0 )
-    {
-      Array<symbol_record *> xsymbols = top_level_sym_tab->symbol_list ( string_vector(), 0xFF, SYMTAB_ALL_SCOPES);
-      Array<symbol_record *> xsubsymbols = top_level_sym_tab->subsymbol_list ( string_vector(), 0xFF, SYMTAB_ALL_SCOPES);
-
-      int sym_len = xsymbols.length (), subsym_len = xsubsymbols.length (),
-                                                     len = sym_len + subsym_len;
-
-      Array<symbol_record *> symbols (len);
-
-      if (len > 0)
-      {
-        //size_t bytes = 0;
-        //size_t elements = 0;
-
-        int i;
-
-        // Joining symbolic tables.
-        for (i = 0; i < sym_len; i++)
-          symbols(i) = xsymbols(i);
-
-        for (i = 0; i < subsym_len; i++)
-          symbols(i+sym_len) = xsubsymbols(i);
-      }
-
-      for (int j = 0; j < len; j++)
-      {
-        if ( symbols(j)->is_user_variable() && 
-	     std::find( variables_request_list.begin(), variables_request_list.end(), 
-			symbols(j)->name() ) != variables_request_list.end() )
-        {
-          requested_variable_t tempVar;
-          tempVar.name = symbols(j)->name();
-          tempVar.ov = symbols(j);
-          requested_variables.push_back(tempVar);
-        }
-      }
-
-    }
-  }
-
-  variables_request_list = std::vector<std::string>();
-  */
-  return 0;
-}
-
-
-//*************************************************************************
-int OctaveLink::setHistoryList( void )
-{
-  // Build up the current list
-  int currentLen = command_history::length();
-  if ( currentLen != m_previousHistoryLength )
-  {
-    for( int i = m_previousHistoryLength ; i < currentLen ; i++ )
-      m_historyList.append( command_history::get_entry(i) );
-    m_previousHistoryLength = currentLen;
-  }
-
-  return 0;
+    fetchHistory();
 }
 
-//*************************************************************************
-int OctaveLink::setBreakPointList( void )
-{
-  // Set the list of breakpoints
-  m_currentBreakpoints = std::vector<BreakPoint>();
-
-  octave_value_list zz;
-  
-  bp_table::fname_line_map bp_list = bp_table::get_breakpoint_list(zz);
-  for (bp_table::fname_line_map_iterator it = bp_list.begin () ; it != bp_list.end () ; it++)
-  {	  
-    bp_table::intmap m = it->second;
-    size_t nel = m.size ();
-    for (size_t j = 0; j < nel; j++)
-
-    {
-      BreakPoint tmp;
-      tmp.fileName = it->first;
-      tmp.lineNumber = m[j];
-
-      m_currentBreakpoints.push_back (tmp);
-    }
-  }
-
-  // If in debug mode, set the location of the break
-  m_reachedBreakpoints = std::vector<BreakPoint>();
-
-  octave_user_code *dbg_fcn = get_user_code ();
-
-  if (dbg_fcn)
-    {
-      bool have_file = true;
-
-      std::string name = dbg_fcn->fcn_file_name ();
-
-      if (name.empty ())
-        {
-          have_file = false;
-	  
-          name = dbg_fcn->name ();
-        }
-
-      //octave_stdout << "stopped in " << name << " at ";
-
-      int l = octave_call_stack::caller_user_code_line ();
-
-      if (l > 0)
-        {
-
-	  BreakPoint tmp;
-	  QFileInfo pathInfo;
-	  QString qFilePath (name.c_str());
-	  pathInfo.setFile (qFilePath);
-	  //(QString (name));
-	  QString fileName (pathInfo.fileName ());
-	  //std::string shortName = Glib::path_get_basename(name);
-	  std::string shortName = fileName.toStdString ();
-	  std::string funcName;
-          int dot = shortName.find_first_of(".");
-          if (dot!=(signed)std::string::npos)
-	    {
-	      funcName = shortName.substr (0,dot);
-	    }
-          tmp.fileName = funcName;
-          tmp.lineNumber = l;
-	  
-	  //	  octave_stdout << "BP reached at " << tmp.filename << ":" << tmp.line_number << std::endl;
-
-          m_reachedBreakpoints.push_back (tmp);
-        }
-      else
-        octave_stdout << " <unknown line>" << std::endl;
-    }
-  return 0;
-}
-
-//*************************************************************************
-int OctaveLink::process_breakpoint_action (void)
-{
-
-  if (Vdebugging)
-  {
-    if (m_breakPointAction==StepInto)
-    {
-      Vdebugging = false;
-      tree_evaluator::dbstep_flag = -1;
-
-      rl_line_buffer[0] = '\0';	
-      rl_point = rl_end = 0;
-      rl_done = 1;
-      rl_forced_update_display ();
-    }
-    else if (m_breakPointAction==StepOver)
-    {
-      Vdebugging = false;
-      tree_evaluator::dbstep_flag = 1;
-
-      rl_line_buffer[0] = '\0';	
-      rl_point = rl_end = 0;
-      rl_done = 1;
-      rl_forced_update_display ();
-    }
-    else if (m_breakPointAction==StepOut)
-    {
-      Vdebugging = false;
-      tree_evaluator::dbstep_flag = -2;
-
-      rl_line_buffer[0] = '\0';	
-      rl_point = rl_end = 0;
-      rl_done = 1;
-      rl_forced_update_display ();
-
-      
-    }
-    else if (m_breakPointAction==Continue)
-    {
-      Vdebugging = false;
-      tree_evaluator::dbstep_flag = 0;
-
-      rl_line_buffer[0] = '\0';	
-      rl_point = rl_end = 0;
-      rl_done = 1;
-      rl_forced_update_display ();
-    }
-    else if (m_breakPointAction==Break)
-    {
-      tree_evaluator::dbstep_flag = 0;
-      octave_throw_interrupt_exception ();
-
-      rl_line_buffer[0] = '\0';	
-      rl_point = rl_end = 0;
-      rl_done = 1;
-      rl_forced_update_display ();
-    }
-    m_breakPointAction = None;
-  }
-
-  return 0;
-}
-
-//*************************************************************************
-int OctaveLink::processBreakpointAndRemoveModify(void)
-{
-  //octave_stdout << "Processing breakpoints changes" << std::endl;
-  // Process added breakpoints
-  for (int i = 0 ; i < (signed)m_addedBreakpoints.size() ; i++)
-  {
-    std::string funcName = m_addedBreakpoints[i].fileName;
-    bp_table::intmap lines;
-    lines[0] = m_addedBreakpoints[i].lineNumber;
-    bp_table::add_breakpoint (funcName,lines);
-    octave_stdout << "Adding breakpoint: " << funcName << " : " << lines[0] << std::endl; 
-  }
-  m_addedBreakpoints = std::vector<BreakPoint>();
-
-  // Process removed breakpoints
-  for (int i = 0 ; i < (signed)m_removedBreakpoints.size() ; i++)
-  {
-    std::string funcName = m_removedBreakpoints[i].fileName;
-    bp_table::intmap lines;
-    lines[0] = m_removedBreakpoints[i].lineNumber;
-    bp_table::remove_breakpoint (funcName,lines);
-    //octave_stdout << "Removing breakpoint: " << funcName << " : " << lines[0] << std::endl; 
-  }
-  m_removedBreakpoints = std::vector<BreakPoint>();
-  return 0;
-}
--- a/gui//src/OctaveLink.h
+++ b/gui//src/OctaveLink.h
@@ -91,161 +91,48 @@
     static QString octaveValueAsQString(OctaveValue octaveValue);
 
     /**
-     * Enumeration used to identify breakpoint actions
-     */
-    enum BreakPointAction
-    {
-        None,
-        StepInto,
-        StepOver,
-        StepOut,
-        Continue,
-        Break
-    };
+      * Returns a copy of the current symbol table buffer.
+      * \return Copy of the current symbol table buffer.
+      */
+    QList<SymbolRecord> currentSymbolTable();
 
     /**
-     * Structure used to store breakpoint info.
-     *
-     * Notes: used for add, remove, list operations, as well as for the BreakpointReached event.
-     */
-    typedef struct BreakPoint
-    {
-        /**
-        * The full path and filename where the breakpoint resides.
-        */
-        std::string fileName;
-
-        /**
-        * The line number where the breakpoint resides.
-        * In the future, -1 can indicate an existing but disabled breakpoint.  This
-        * assumes that no one will ever have an M file longer than 2Million lines.
-        */
-        int lineNumber;
-    } BreakPoint;
-
-    typedef struct RequestedVariable
-    {
-        std::string name;
-        octave_value ov;
-    } RequestedVariable;
-
-    // Functions used to access data form the client side.
-    /** Debugging related methods. */
+      * Returns a copy of the current history buffer.
+      * \return Copy of the current history buffer.
+      */
+    string_vector currentHistory();
 
-    /** TODO: Describe. */
-    std::vector<BreakPoint> breakPointList(int& status);
-
-    /** TODO: Describe. */
-    std::vector<BreakPoint> reachedBreakpoint();
-
-    /** TODO: Describe. */
-    bool isBreakpointReached();
-
-    /** TODO: Describe. */
-    int addBreakpoint(BreakPoint bp_info);
-
-    /** TODO: Describe. */
-    int	removeBreakpoint(BreakPoint bp_info);
-
-    /** TODO: Describe. */
-    int	modifyBreakpoint(BreakPoint old_bp_info, BreakPoint new_bp_info);
-
-    /** TODO: Describe. */
-    int	setBreakpointAction(BreakPointAction action);
-
-    QList<SymbolRecord> currentSymbolTable();
-
-    /** TODO: Describe. */
-    QList<RequestedVariable> requestedVariables(void);
-
-    /** TODO: Describe. */
-    int	setRequestedVariableNames(QList<QString> variableNames);
+    void processOctaveServerData();
 
     /**
-      * History related methods.
+      * Updates the current symbol table with new data
+      * from octave.
       */
-    string_vector getHistoryList(void);
-
-    // FUNCTIONS USED TO ACCESS DATA FROM THE OCTAVE SERVER SIDE
+    void fetchSymbolTable();
 
-    // NOTE: THIS IMPLIES THAT THESE ARE ONLY CALLED FROM
-    // OCTAVE DURING A TIME IN WHICH THINGS ARE KNOWN TO
-    // BE "THREAD-SAFE".  PROPOSED LOCATIONS:
-    //   src/toplev.cc - main_loop() at the end of the do...while
-    //   src/pt-bp.h   - MAYBE_DO_BREAKPOINT just prior to the do_keyboard
-    // Most of these will call octave API functions to "pull" the data, rather
-    // than having octave pass in the data.  This will help make changes
-    // exlusive to this class if/when the Octave API changes.
     /**
-     * Calls all the appropriate functions that follow to update Octave
-     * according to the data sent from the client in a thread-safe manner.
-     *
-     * Algorithm:
-     *   Acquire lock
-     *   process_breakpoint_add_remove_modify
-     *   set_current_breakpoint
-     *   set_breakpoint_list
-     *   ...http://oregano.gforge.lug.fi.uba.ar/
-     *   Release lock
-     */
-    int processOctaveServerData(void);
-
-    /** Debugging related methods. */
-    /** TODO: Describe. */
-    int setBreakPointList(void);
-
-    /** TODO: Describe. */
-    // duplicate of process_breakpoint_action or helper function???
-    int setCurrentBreakpoint(std::string filename, int line_number);
-
-    /** TODO: Describe. */
-    int processBreakpointAndRemoveModify(void);
-
-    /** TODO: Describe. */
-    int process_breakpoint_action(void);
-
-    /** Variable related methods. */
-    /** Retrieves all variables from Octave. */
-    void fetchSymbolTable(void);
-
-    /** TODO: Describe. */
-    int processRequestedVariables(void);
-
-    /** History related methods. */
-    /** TODO: Describe. */
-    int setHistoryList(void);
+      * Updates the current history buffer with new data
+      * from octave.
+      */
+    void fetchHistory();
 
 signals:
     void symbolTableChanged();
+    void historyChanged();
 
 private:
     OctaveLink();
     ~OctaveLink();
 
-    /** Mutex variable used to protect access to internal class data. */
-    QMutex m_internalAccessMutex;
-
-    std::vector<BreakPoint> m_currentBreakpoints;
-    std::vector<BreakPoint> m_reachedBreakpoints;
-    std::vector<BreakPoint> m_addedBreakpoints;
-    std::vector<BreakPoint> m_removedBreakpoints;
-    std::vector<BreakPoint> m_modifiedBreakpointsOld;
-    std::vector<BreakPoint> m_modifiedBreakpointsNew;
-    BreakPointAction m_breakPointAction;
-
     /** Variable related member variables. */
     QSemaphore *m_symbolTableSemaphore;
     QList<SymbolRecord> m_symbolTableBuffer;
-    QList<QString> m_variablesRequestList;
-
-    // NOTE: Create an overloaded operator<< for octave_value to do the
-    // flattening.  This will allow us to append easily to an ostringstream
-    // for output.
-    QList<RequestedVariable> m_requestedVariables;
 
     /** History related member variables. */
-    string_vector m_historyList;
+    QSemaphore *m_historySemaphore;
+    string_vector m_historyBuffer;
     int m_previousHistoryLength;
+
     static OctaveLink m_singleton;
 };
 #endif // OCTAVELINK_H