Changeset 2671 in Sophya for trunk/SophyaLib/SysTools


Ignore:
Timestamp:
Apr 18, 2005, 5:34:31 PM (20 years ago)
Author:
ansari
Message:

Modifs pour introduire la possibilite d'execution multi-thread de commandes ds l'interpreteur Commander - Reza 18/4/2005

Location:
trunk/SophyaLib/SysTools
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/SophyaLib/SysTools/commander.cc

    r2615 r2671  
    1212#include "rpneval.h"
    1313#include "srandgen.h"
     14#include "zthread.h"
    1415
    1516
     
    331332}
    332333
     334
     335// ------------------------------------------------------------
     336//         Classe CommandExeThr
     337// ------------------------------------------------------------
     338/*!
     339  \internal
     340  \class SOPHYA::CommandExeThr
     341  \ingroup SysTools
     342  Class for internal use by class Commander for command execution in separate threads.
     343*/
     344class CommandExeThr :  public ZThread  {
     345public:
     346                 CommandExeThr(uint_8 id, CmdExecutor * cmdex, string& keyw,
     347                               vector<string>& args, string& toks);
     348  virtual void   run();
     349  inline  uint_8 Id() { return _id; }
     350  inline  bool   IfDone() { return _fgdone; }
     351  inline  string& Tokens() { return  _toks; }
     352  inline  string& Keyword() { return  _keyw; }
     353protected:
     354  uint_8 _id;
     355  CmdExecutor * _cmdex;
     356  string _keyw, _toks;
     357  vector<string> _args;
     358  bool _fgdone;
     359};
     360
     361/* --Methode-- */
     362CommandExeThr::CommandExeThr(uint_8 id, CmdExecutor * cmdex, string& keyw,
     363                               vector<string>& args, string& toks)
     364{
     365  _id = id;
     366  _cmdex = cmdex;
     367  _keyw = keyw;
     368  if (args.size() > 1)
     369    for(size_t k=0; k<args.size()-1; k++) _args.push_back(args[k]);
     370  _toks = toks;
     371  for(size_t k=_toks.size()-1; k>0; k--)
     372    if (_toks[k] == '&') { _toks[k] = ' '; break; }
     373  _fgdone = false;
     374}
     375
     376/* --Methode-- */
     377void CommandExeThr::run()
     378{
     379  int rc = _cmdex->Execute(_keyw, _args, _toks);
     380  _fgdone = true;
     381  setRC(rc);
     382}
     383
    333384// ------------------------------------------------------------
    334385//         Classe Commander
     
    345396  to applications.
    346397
    347   Although the insterpreter has many limitations compared to
     398  Although the interpreter has many limitations compared to
    348399  c-shell, or Tcl , it provides some interesting possibilities:
    349400
     
    400451curtestresult = true;
    401452
     453// Pour la numerotation et l'identification des threads
     454ThrId = 0;
     455
    402456// Numero de help-groupe courant - Le premier groupe ajoute aura un gid = 1
    403457// gid = 0 n'existe pas : c'est le groupe de toutes les commandes
     
    411465string usage;
    412466usage = ">>> (Commander) Interpreter's keywords : \n";
    413 usage += "  > set varname string   # To set a variable, $varname \n";
     467usage += "  > set varname string     # To set a variable, $varname \n";
    414468usage += "  > unset varname          # clear variable definition \n";
    415469usage += "  > rpneval varname RPNExpression  # Reverse Polish Notation evaluation \n";
     
    436490usage += "  > listscripts   # List of all known scripts \n";
    437491usage += "  > clearcript    # Clear a script definition \n";
     492usage += "  > thrlist       # List of command execution threads (& as the last character) \n";
     493usage += "  > clearthrlist  # Removes finished threads from the list  \n";
     494usage += "  > cancelthr Id  # Cancel a given thread (ThrId=id)  \n";
     495usage += "  > waitthr       # Waits until all active threads have finished (join()) \n";
    438496usage += "  > exec filename # Execute commands from file \n";
    439497usage += "  > help <command_name>  # <command_name> usage info \n";   
     
    475533RegisterCommand(kw, usage, NULL, grp);
    476534
     535kw = "CExpEvaluator";
     536usage  = "> Evaluation of C-like expression (used in V = C-like-Expression) \n";
     537usage += "   >>> Arithmetic operators, parenthesis ( + - * / ) \n";
     538usage += "   >>> Functions : sqrt fabs floor hypot \n";
     539usage += "   ...  exp log log10 pow  ; sinh cosh tanh \n";
     540usage += "   ...  sin cos tan asin acos atan atan2  \n";
     541usage += "   ...  rand01()  randpm1() gaurand() \n";
     542usage += "   >>> Constants : Pi = M_PI E = M_E \n";
     543usage += "   Example: x = 5.*(2.+sin(0.3*Pi))";
     544RegisterCommand(kw, usage, NULL, grp);
     545
    477546kw = "shell execute";
    478547usage  = "> shell  command_string  # Execute  shell command\n";
     
    656725/* --Methode-- */
    657726/*!
    658   \brief Method which has to be invoked to interpret a giev command line or string.
     727  \brief Method which has to be invoked to interpret a given command line or string.
    659728*/
    660729int Commander::Interpret(string& s)
     
    662731int rc = 0;
    663732ScriptList::iterator sit;
     733
     734// Si le flag d'arret d'execution a ete positionne on returne avec le code
     735//  de BREAKEXECUTION
     736if (fgexebrk) {
     737  cout << " ===> Commander::Interpret() - STOP Execution (CMD_BREAKEXE_RC)" << endl;
     738  fgexebrk = false; return CMD_BREAKEXE_RC;
     739}
    664740
    665741// On saute de commandes vides
     
    769845// On verifie si nous sommes dans un bloc (for , foreach)
    770846if (CmdBlks.top() != NULL)  { // On est dans un bloc
    771   if ( (kw == "for") || (kw == "foreach")) felevel++;
     847  if ( (kw == "for") || (kw == "foreach") || (kw == "forinfile") ) felevel++;
    772848  else if (kw == "end") felevel--;
    773849  if (felevel == 0) { // Il faut executer le bloc
     
    777853    if (!curb->CheckBloc()) {
    778854      cerr << "Commander::Interpret()/syntax error - unbalenced if ... endif"
    779            << " within for/foreach bloc ! " << endl;
     855           << " within for/foreach/forinfile bloc ! " << endl;
    780856      delete curb;
    781857      _xstatus = 93;
     
    803879}
    804880else if (kw == "end") {
    805   cerr << "Commander::Interpret()/syntax error - end outside for/foreach bloc \n"
     881  cerr << "Commander::Interpret()/syntax error - end outside for/foreach/forinfile bloc \n"
    806882       << "line: " << s << endl;
    807883  _xstatus = 94;
     
    10011077
    10021078return(0);
     1079}
     1080
     1081void  Commander::StopExecution()
     1082{
     1083  fgexebrk = true;
    10031084}
    10041085
     
    17621843  }
    17631844}
     1845//---------------------------------------------
     1846//---   Commandes de gestion des threads ------
     1847//---------------------------------------------
     1848else if (kw == "thrlist") {
     1849  ListThreads();
     1850  return(0);
     1851}
     1852else if (kw == "cancelthr") {
     1853  if (tokens.size() < 1) { cout << "Commander::Interpret() Usage: cancelthr thrid" << endl;  return(0); }
     1854  uint_8  id = atol(tokens[0].c_str());
     1855  CancelThr(id);
     1856  return (0);
     1857}
     1858else if (kw == "waitthr") {
     1859  WaitThreads();
     1860  return (0);
     1861}
     1862else if (kw == "cleanthrlist") {
     1863  CleanThrList();
     1864  return (0);
     1865
     1866
    17641867else if (kw == "traceon")  { cout << "Commander::Interpret()  -> Trace ON mode " << endl; trace = true; }
    17651868else if (kw == "traceoff") { cout << "Commander::Interpret()  -> Trace OFF mode " << endl; trace = false; }
     
    18201923  if (it == cmdexmap.end())  cout << "No such command : " << keyw << " ! " << endl;
    18211924  else {
    1822     if ((*it).second.cex) rc = (*it).second.cex->Execute(keyw, args, toks);
     1925    if ((*it).second.cex) {
     1926      // Doit-on l'executer sous forme de thread separe ?
     1927      if ((args.size()>0) && (args[args.size()-1] == "&")) {
     1928        ThrId++;
     1929        CommandExeThr * thr = new CommandExeThr(ThrId, (*it).second.cex, keyw, args, toks);
     1930        CmdThrExeList.push_back(thr);
     1931        cout << " Commander::ExecuteCommand() : Thread execution of command " << keyw << endl;
     1932        thr->start();   
     1933        rc = 0;
     1934      }
     1935      else rc = (*it).second.cex->Execute(keyw, args, toks);
     1936    }
    18231937    else cout << "Dont know how to execute " << keyw << " ? " << endl;
    18241938    }
     
    18771991
    18781992return(0);
     1993}
     1994
     1995/* --Methode-- */
     1996void Commander::ListThreads()
     1997{
     1998  cout << "---- Commander::ListThreads()  List of separate execution threads NThread="
     1999       <<  CmdThrExeList.size() << " ----- " << endl;
     2000  for(list<CommandExeThr *>::iterator tit = CmdThrExeList.begin();
     2001      tit != CmdThrExeList.end(); tit++) {
     2002    cout << "Id=" << (*tit)->Id();
     2003    if ( (*tit)->IfDone() )  cout << " Finished , Rc= " << (*tit)->getRC();
     2004    else cout << " Executing";
     2005    cout << " (Cmd= " << (*tit)->Keyword() << " " << (*tit)->Tokens() << " )" << endl;
     2006  }
     2007}
     2008/* --Methode-- */
     2009void Commander::CancelThr(uint_8 id)
     2010{
     2011  for(list<CommandExeThr *>::iterator tit = CmdThrExeList.begin();
     2012      tit != CmdThrExeList.end(); tit++) {
     2013    if ((*tit)->Id() == id) {
     2014      (*tit)->cancel(); 
     2015      cout << "Commander::CancelThr()  Thread Id= " << id << " cancelled" << endl;
     2016      return;
     2017    }
     2018  }
     2019  cout << "Commander::CancelThr()/Error: No thread with Id= " << id << endl;
     2020}
     2021
     2022/* --Methode-- */
     2023void Commander::CleanThrList()
     2024{
     2025  cout << "---- Commander::CleanThrList()  Cleaning thrlist  ----- \n";
     2026  list<CommandExeThr *> thrcopie;
     2027  for(list<CommandExeThr *>::iterator tit = CmdThrExeList.begin();
     2028      tit != CmdThrExeList.end(); tit++) {
     2029    if ( (*tit)->IfDone() ) {
     2030      cout << " Thread Id= " << (*tit)->Id() << " rc= " << (*tit)->getRC() << " Cleaned" << endl;
     2031      delete (*tit);
     2032    }
     2033    else thrcopie.push_back((*tit));
     2034  }
     2035  CmdThrExeList = thrcopie;
     2036  cout << " ... " << CmdThrExeList.size() << " threads still active " << endl;
     2037}
     2038
     2039/* --Methode-- */
     2040void Commander::WaitThreads()
     2041{
     2042  cout << "---- Commander::WaitThreads()  Wait/Join command execution threads - NThread="
     2043       <<  CmdThrExeList.size() << " ----- " << endl;
     2044  for(list<CommandExeThr *>::iterator tit = CmdThrExeList.begin();
     2045      tit != CmdThrExeList.end(); tit++) {
     2046    try {
     2047      if (! (*tit)->IfDone())  (*tit)->join();
     2048    }
     2049    catch (std::exception & e) {
     2050      cout << " Commander::WaitThreads()/Exception msg= " << e.what() << endl;
     2051    }
     2052    cout << " Joined thread Id= " << (*tit)->Id() << " rc= " << (*tit)->getRC() << endl;
     2053    delete (*tit);
     2054  }
     2055  CmdThrExeList.erase(CmdThrExeList.begin(), CmdThrExeList.end());
    18792056}
    18802057
  • trunk/SophyaLib/SysTools/commander.h

    r2598 r2671  
    5959class CommanderBloc;    // Bloc de type foreach / for de l'interpreteur Commander
    6060class CommanderScript;  // Script de commandes defini ds l'interpreteur Commander
    61 
    62 //! A simple command interpreter with c-shell like syntax with dynamic load capability.
     61class CommandExeThr;    // Thread d'execution de commande
     62
     63//! A simple command interpreter with c-shell like syntax and  dynamic load capability.
    6364
    6465class Commander : public CmdInterpreter  {
     
    8586
    8687  virtual int           Interpret(string& line);
     88  virtual void          StopExecution();
    8789
    8890  virtual int           ExecuteCommand(string& keyw, vector<string>& args, string& toks);
     
    162164  void          PopStack(bool psta=true);
    163165
     166  //   Gestion des threads d'execution de commandes
     167  void          ListThreads();
     168  void          CancelThr(uint_8 thrid);
     169  void          CleanThrList();
     170  void          WaitThreads();
     171
     172// ------ Attributs et variables ------
    164173  CmdInterpreter* curcmdi;
    165174
     
    180189  CmdExmap helpexmap;                                  // Pour les helps sans commande
    181190
     191// Pour garder la liste des threads d'execution de commande
     192  list<CommandExeThr *> CmdThrExeList;
     193  uint_8 ThrId;
     194
    182195// Pour garder la liste des modules
    183196  typedef map<string, PDynLinkMgr* , less<string> > Modmap;
  • trunk/SophyaLib/SysTools/zthread.h

    r2598 r2671  
    3939  inline void   setRC(int rc) { _rc = rc; }
    4040  //! Return the value of the return code for the thread object
    41   inline int    getRC(int rc) { return(_rc);
     41  inline int    getRC() { return(_rc);
    4242 }
    4343  inline void   setAction(ZThreadAction act, void * usp=NULL)
Note: See TracChangeset for help on using the changeset viewer.