Threads management modified to execute all scilab script in the main thread. 94/16994/5
Cedric Delamarre [Wed, 5 Aug 2015 13:50:09 +0000 (15:50 +0200)]
Change-Id: If546fb624ac93005df24a1c22050d3e01cf396f8

12 files changed:
scilab/modules/ast/core_Import.def
scilab/modules/ast/includes/system_env/threadmanagement.hxx
scilab/modules/ast/src/cpp/ast/runvisitor.cpp
scilab/modules/ast/src/cpp/system_env/threadmanagement.cpp
scilab/modules/core/includes/runner.hxx
scilab/modules/core/sci_gateway/cpp/sci_abort.cpp
scilab/modules/core/sci_gateway/cpp/sci_exit.cpp
scilab/modules/core/sci_gateway/cpp/sci_pause.cpp
scilab/modules/core/sci_gateway/cpp/sci_quit.cpp
scilab/modules/core/src/cpp/InitScilab.cpp
scilab/modules/core/src/cpp/runner.cpp
scilab/modules/core/src/cpp/tasks.cpp

index 424586c..7ebc756 100644 (file)
@@ -4,3 +4,7 @@ LIBRARY    core.dll
 EXPORTS
 MyHeapFree
 MyHeapAlloc
+StaticRunner_launch
+StaticRunner_isRunnerAvailable
+StaticRunner_isInterruptibleCommand
+StaticRunner_setInterruptibleCommand
index 7b2cf69..2c5d9cd 100644 (file)
@@ -20,6 +20,8 @@ extern "C"
 #include "dynlib_ast.h"
 }
 
+//#define DEBUG_THREAD
+
 class EXTERN_AST ThreadManagement
 {
 private :
@@ -27,7 +29,6 @@ private :
     static __threadLock m_StartLock;
     static __threadLock m_ParseLock;
     static __threadLock m_StoreCommandLock;
-    static __threadLock m_AstLock;
 
     static __threadSignal m_ConsoleExecDone;
     static __threadSignalLock m_ConsoleExecDoneLock;
@@ -35,8 +36,8 @@ private :
     static __threadSignal m_AwakeRunner;
     static __threadSignalLock m_AwakeRunnerLock;
 
-    static __threadSignal m_AstPending;
-    static __threadSignalLock m_AstPendingLock;
+    static __threadSignal m_AvailableRunner;
+    static __threadSignalLock m_AvailableRunnerLock;
 
     static __threadSignal m_StartPending;
     static __threadSignalLock m_StartPendingLock;
@@ -44,12 +45,16 @@ private :
     static __threadSignal m_CommandStored;
     static __threadSignalLock m_CommandStoredLock;
 
+    static __threadSignal m_RunMe;
+    static __threadSignalLock m_RunMeLock;
+
     // used to avoid "Spurious Wakeups"
-    static bool m_AstPendingWasSignalled;
+    static bool m_AvailableRunnerWasSignalled;
     static bool m_ConsoleExecDoneWasSignalled;
     static bool m_AwakeRunnerWasSignalled;
     static bool m_StartPendingWasSignalled;
     static bool m_CommandStoredWasSignalled;
+    static bool m_RunMeWasSignalled;
 
 public :
     static void initialize(void);
@@ -62,11 +67,9 @@ public :
     static void UnlockStoreCommand(void);
     static void LockRunner(void);
     static void UnlockRunner(void);
-    static void LockAst(void);
-    static void UnlockAst(void);
 
-    static void SendAstPendingSignal(void);
-    static void WaitForAstPendingSignal(void);
+    static void SendAvailableRunnerSignal(void);
+    static void WaitForAvailableRunnerSignal(void);
     static void SendConsoleExecDoneSignal(void);
     static void WaitForConsoleExecDoneSignal(void);
     static void SendAwakeRunnerSignal(void);
@@ -75,6 +78,8 @@ public :
     static void WaitForStartPendingSignal(void);
     static void SendCommandStoredSignal(void);
     static void WaitForCommandStoredSignal(void);
+    static void SendRunMeSignal(void);
+    static void WaitForRunMeSignal(void);
 
 };
 
index 325d552..4d00dc2 100644 (file)
@@ -611,20 +611,7 @@ void RunVisitorT<T>::visitprivate(const ReturnExp &e)
         if (ConfigVariable::getPauseLevel() != 0 && symbol::Context::getInstance()->getScopeLevel() == ConfigVariable::getActivePauseLevel())
         {
             //return or resume
-            ThreadId* pThreadId = ConfigVariable::getLastPausedThread();
-            if (pThreadId == NULL)
-            {
-                //no paused thread, so just go leave
-                return;
-            }
-
-            //force exit without prompt of current thread ( via Aborted status )
-            ThreadId* pMe = ConfigVariable::getThread(__GetCurrentThreadKey());
-            pMe->setStatus(ThreadId::Aborted);
-
-            //resume previous execution thread
-            pThreadId->resume();
-
+            ConfigVariable::DecreasePauseLevel();
             return;
         }
         else
@@ -918,8 +905,6 @@ void RunVisitorT<T>::visitprivate(const SelectExp &e)
 template <class T>
 void RunVisitorT<T>::visitprivate(const SeqExp  &e)
 {
-    types::ThreadId* pThreadMe = ConfigVariable::getThread(__GetCurrentThreadKey());
-
     for (auto exp : e.getExps())
     {
         if (exp->isCommentExp())
@@ -927,14 +912,12 @@ void RunVisitorT<T>::visitprivate(const SeqExp  &e)
             continue;
         }
 
-        ThreadManagement::LockAst();
-        if (pThreadMe && pThreadMe->getInterrupt())
+        // interrupt me to execute a prioritary command
+        while (StaticRunner_isInterruptibleCommand() == 1 && StaticRunner_isRunnerAvailable() == 1)
         {
-            ThreadManagement::SendAstPendingSignal();
-            ThreadManagement::UnlockAst();
-            pThreadMe->suspend();
+            StaticRunner_launch();
+            StaticRunner_setInterruptibleCommand(1);
         }
-        ThreadManagement::UnlockAst();
 
         try
         {
index 6376b91..132bf2d 100644 (file)
@@ -12,7 +12,6 @@
 
 #include "threadmanagement.hxx"
 
-//#define DEBUG_THREAD
 #ifdef DEBUG_THREAD
 #include <iostream>
 #endif // DEBUG_THREAD
@@ -21,7 +20,6 @@ __threadLock ThreadManagement::m_StartLock;
 __threadLock ThreadManagement::m_RunnerLock;
 __threadLock ThreadManagement::m_ParseLock;
 __threadLock ThreadManagement::m_StoreCommandLock;
-__threadLock ThreadManagement::m_AstLock;
 
 __threadSignal ThreadManagement::m_ConsoleExecDone;
 __threadSignalLock ThreadManagement::m_ConsoleExecDoneLock;
@@ -29,8 +27,8 @@ __threadSignalLock ThreadManagement::m_ConsoleExecDoneLock;
 __threadSignal ThreadManagement::m_AwakeRunner;
 __threadSignalLock ThreadManagement::m_AwakeRunnerLock;
 
-__threadSignal ThreadManagement::m_AstPending;
-__threadSignalLock ThreadManagement::m_AstPendingLock;
+__threadSignal ThreadManagement::m_AvailableRunner;
+__threadSignalLock ThreadManagement::m_AvailableRunnerLock;
 
 __threadSignal ThreadManagement::m_StartPending;
 __threadSignalLock ThreadManagement::m_StartPendingLock;
@@ -38,11 +36,15 @@ __threadSignalLock ThreadManagement::m_StartPendingLock;
 __threadSignal ThreadManagement::m_CommandStored;
 __threadSignalLock ThreadManagement::m_CommandStoredLock;
 
-bool ThreadManagement::m_AstPendingWasSignalled         = false;
+__threadSignal ThreadManagement::m_RunMe;
+__threadSignalLock ThreadManagement::m_RunMeLock;
+
+bool ThreadManagement::m_AvailableRunnerWasSignalled         = false;
 bool ThreadManagement::m_ConsoleExecDoneWasSignalled    = false;
 bool ThreadManagement::m_AwakeRunnerWasSignalled        = false;
 bool ThreadManagement::m_StartPendingWasSignalled       = false;
 bool ThreadManagement::m_CommandStoredWasSignalled      = false;
+bool ThreadManagement::m_RunMeWasSignalled              = false;
 
 void ThreadManagement::initialize()
 {
@@ -50,7 +52,6 @@ void ThreadManagement::initialize()
     __InitLock(&m_StartLock);
     __InitLock(&m_ParseLock);
     __InitLock(&m_StoreCommandLock);
-    __InitLock(&m_AstLock);
 
     __InitSignal(&m_AwakeRunner);
     __InitSignalLock(&m_AwakeRunnerLock);
@@ -58,14 +59,17 @@ void ThreadManagement::initialize()
     __InitSignal(&m_ConsoleExecDone);
     __InitSignalLock(&m_ConsoleExecDoneLock);
 
-    __InitSignal(&m_AstPending);
-    __InitSignalLock(&m_AstPendingLock);
+    __InitSignal(&m_AvailableRunner);
+    __InitSignalLock(&m_AvailableRunnerLock);
 
     __InitSignal(&m_StartPending);
     __InitSignalLock(&m_StartPendingLock);
 
     __InitSignal(&m_CommandStored);
     __InitSignalLock(&m_CommandStoredLock);
+
+    __InitSignal(&m_RunMe);
+    __InitSignalLock(&m_RunMeLock);
 }
 
 void ThreadManagement::LockStart(void)
@@ -132,46 +136,29 @@ void ThreadManagement::UnlockRunner(void)
     __UnLock(&m_RunnerLock);
 }
 
-void ThreadManagement::LockAst(void)
-{
-#ifdef DEBUG_THREAD
-    std::cout << "[" << __GetCurrentThreadKey() << "] " << "LockAst" << std::endl;
-#endif // DEBUG_THREAD
-    __Lock(&m_AstLock);
-}
-
-void ThreadManagement::UnlockAst(void)
-{
-#ifdef DEBUG_THREAD
-    std::cout << "[" << __GetCurrentThreadKey() << "] " << "UnlockAst" << std::endl;
-#endif // DEBUG_THREAD
-    __UnLock(&m_AstLock);
-}
-
-void ThreadManagement::SendAstPendingSignal(void)
+void ThreadManagement::SendAvailableRunnerSignal(void)
 {
 #ifdef DEBUG_THREAD
-    std::cout << "[" << __GetCurrentThreadKey() << "] " << "SendAstPendingSignal" << std::endl;
+    std::cout << "[" << __GetCurrentThreadKey() << "] " << "SendAvailableRunnerSignal" << std::endl;
 #endif // DEBUG_THREAD
-    __LockSignal(&m_AstPendingLock);
-    m_AstPendingWasSignalled = true;
-    __Signal(&m_AstPending);
-    __UnLockSignal(&m_AstPendingLock);
+    __LockSignal(&m_AvailableRunnerLock);
+    m_AvailableRunnerWasSignalled = true;
+    __Signal(&m_AvailableRunner);
+    __UnLockSignal(&m_AvailableRunnerLock);
 }
 
-void ThreadManagement::WaitForAstPendingSignal(void)
+void ThreadManagement::WaitForAvailableRunnerSignal(void)
 {
 #ifdef DEBUG_THREAD
-    std::cout << "[" << __GetCurrentThreadKey() << "] " << "WaitForAstPendingSignal" << std::endl;
+    std::cout << "[" << __GetCurrentThreadKey() << "] " << "WaitForAvailableRunnerSignal" << std::endl;
 #endif // DEBUG_THREAD
-    __LockSignal(&m_AstPendingLock);
-    ThreadManagement::UnlockAst();
-    m_AstPendingWasSignalled = false;
-    while (m_AstPendingWasSignalled == false)
+    __LockSignal(&m_AvailableRunnerLock);
+    m_AvailableRunnerWasSignalled = false;
+    while (m_AvailableRunnerWasSignalled == false)
     {
-        __Wait(&m_AstPending, &m_AstPendingLock);
+        __Wait(&m_AvailableRunner, &m_AvailableRunnerLock);
     }
-    __UnLockSignal(&m_AstPendingLock);
+    __UnLockSignal(&m_AvailableRunnerLock);
 
 }
 
@@ -276,3 +263,28 @@ void ThreadManagement::WaitForCommandStoredSignal(void)
     }
     __UnLockSignal(&m_CommandStoredLock);
 }
+
+void ThreadManagement::SendRunMeSignal(void)
+{
+#ifdef DEBUG_THREAD
+    std::cout << "[" << __GetCurrentThreadKey() << "] " << "SendRunMeSignal" << std::endl;
+#endif // DEBUG_THREAD
+    __LockSignal(&m_RunMeLock);
+    m_RunMeWasSignalled = true;
+    __Signal(&m_RunMe);
+    __UnLockSignal(&m_RunMeLock);
+}
+
+void ThreadManagement::WaitForRunMeSignal(void)
+{
+#ifdef DEBUG_THREAD
+    std::cout << "[" << __GetCurrentThreadKey() << "] " << "WaitForRunMeSignal" << std::endl;
+#endif // DEBUG_THREAD
+    __LockSignal(&m_RunMeLock);
+    m_RunMeWasSignalled = false;
+    while (m_RunMeWasSignalled == false)
+    {
+        __Wait(&m_RunMe, &m_RunMeLock);
+    }
+    __UnLockSignal(&m_RunMeLock);
+}
index 1b63ba0..15dbe57 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
+ *  Copyright (C) 2014-2015 - Scilab Enterprises - Cedric Delamarre
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
 #ifndef __RUNNER_HXX__
 #define __RUNNER_HXX__
 
-#include <iostream>
 #include "exp.hxx"
 #include "execvisitor.hxx"
 
 extern "C"
 {
-#include "Thread_Wrapper.h"
 #include "dynlib_core.h"
 }
 
-#include "threadId.hxx"
-
-
 class CORE_IMPEXP Runner
 {
-private :
+public :
     Runner(ast::Exp* _theProgram, ast::ExecVisitor *_visitor)
     {
         m_theProgram = _theProgram;
         m_visitor = _visitor;
+        m_isConsoleCommand = false;
+    }
+
+    Runner(ast::Exp* _theProgram, ast::ExecVisitor *_visitor, bool _isConsoleCommand, bool _isInterruptible)
+    {
+        m_theProgram = _theProgram;
+        m_visitor = _visitor;
+        m_isConsoleCommand = _isConsoleCommand;
+        m_isInterruptible = _isInterruptible;
     }
 
     ~Runner()
@@ -41,13 +46,6 @@ private :
         delete m_visitor;
     }
 
-public :
-
-    static void execAndWait(ast::Exp* _theProgram, ast::ExecVisitor *_visitor,
-                            bool _isInterruptible, bool _isPrioritary, bool _isConsoleCommand);
-
-    void exec(ast::Exp* _theProgram, ast::ExecVisitor *_visitor);
-
     ast::ExecVisitor *getVisitor()
     {
         return m_visitor;
@@ -58,33 +56,49 @@ public :
         return m_theProgram;
     }
 
-    __threadId getThreadId(void)
+    bool isConsoleCommand()
     {
-        return m_threadId;
+        return m_isConsoleCommand;
     }
 
-    void setThreadId(__threadId _threadId)
+    bool isInterruptible()
     {
-        m_threadId = _threadId;
+        return m_isInterruptible;
     }
 
-    __threadKey getThreadKey(void)
-    {
-        return m_threadKey;
-    }
+private :
+    ast::Exp* m_theProgram;
+    ast::ExecVisitor* m_visitor;
+    bool m_isConsoleCommand;
+    bool m_isInterruptible;
 
-    void setThreadKey(__threadKey _threadId)
-    {
-        m_threadKey = _threadId;
-    }
+    // static members to manage execution
+};
 
-private :
-    static void *launch(void *args);
+class StaticRunner
+{
+public:
+    static void launch(void);
+    static void setRunner(Runner* _RunMe);
+    static Runner* getRunner(void);
+    static bool isRunnerAvailable(void);
+    static bool isInterruptibleCommand(void);
+    static void setInterruptibleCommand(bool _isInterruptible);
+    static void execAndWait(ast::Exp* _theProgram, ast::ExecVisitor *_visitor,
+                            bool _isInterruptible, bool _isPrioritary, bool _isConsoleCommand);
+    static void exec(ast::Exp* _theProgram, ast::ExecVisitor *_visitor);
 
-private :
-    __threadKey m_threadKey;
-    __threadId m_threadId;
-    ast::Exp*           m_theProgram;
-    ast::ExecVisitor*   m_visitor;
+private:
+    static Runner* m_RunMe;
+    static bool m_bInterruptibleCommand;
 };
-#endif /* !__RUNNER_HXX__ */
+
+extern "C"
+{
+    void StaticRunner_launch(void);
+    int StaticRunner_isRunnerAvailable(void);
+    int StaticRunner_isInterruptibleCommand(void);
+    void StaticRunner_setInterruptibleCommand(int val);
+}
+
+#endif /* !__RUNNER_HXX__ */
\ No newline at end of file
index 5196913..3b4817d 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
+ *  Copyright (C) 2015 - Scilab Enterprises - Cedric Delamarre
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
 
 #include "core_gw.hxx"
 #include "function.hxx"
-#include "runner.hxx"
-#include "threadId.hxx"
-#include "double.hxx"
+#include "configvariable.hxx"
 
 extern "C"
 {
 #include "charEncoding.h"
 #include "localization.h"
 #include "Scierror.h"
-
-#include "Thread_Wrapper.h"
 }
 
 types::Function::ReturnValue sci_abort(types::typed_list &in, int _iRetCount, types::typed_list &out)
@@ -39,20 +36,6 @@ types::Function::ReturnValue sci_abort(types::typed_list &in, int _iRetCount, ty
         return types::Function::Error;
     }
 
-    ThreadId* pThreadId = NULL;
-    if (ConfigVariable::getLastPausedThread() == NULL)
-    {
-        throw ast::InternalAbort();
-    }
-    else
-    {
-        while ((pThreadId = ConfigVariable::getLastPausedThread()) != NULL)
-        {
-            __threadId id = pThreadId->getThreadId();
-            pThreadId->abort();
-            __WaitThreadDie(id);
-        }
-    }
-
+    throw ast::InternalAbort();
     return types::Function::OK;
 }
index f50f37d..7484827 100644 (file)
@@ -2,6 +2,7 @@
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
  *  Copyright (C) 2015 - Scilab Enterprises - Anais AUBERT
+ *  Copyright (C) 2015 - Scilab Enterprises - Cedric Delamarre
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
@@ -71,7 +72,6 @@ Function::ReturnValue sci_exit(typed_list &in, int _iRetCount, typed_list &out)
         }
         else
         {
-
             forceCloseMainScilabObject();
         }
     }
@@ -80,6 +80,8 @@ Function::ReturnValue sci_exit(typed_list &in, int _iRetCount, typed_list &out)
     {
         ConfigVariable::setExitStatus((int)dExit);
         ConfigVariable::setForceQuit(true);
+        // go out without continue any execution
+        throw ast::InternalAbort();
     }
     return Function::OK;
 }
index aa8df4e..ed3c5e3 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
+ *  Copyright (C) 2015 - Scilab Enterprises - Cedric Delamarre
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
 #include "function.hxx"
 #include "threadmanagement.hxx"
 #include "configvariable.hxx"
-#include "threadId.hxx"
+#include "runner.hxx"
 
 extern "C"
 {
 #include "charEncoding.h"
 #include "localization.h"
 #include "Scierror.h"
-
-#include "Thread_Wrapper.h"
 }
 
 types::Function::ReturnValue sci_pause(types::typed_list &in, int _iRetCount, types::typed_list &out)
@@ -35,33 +34,22 @@ types::Function::ReturnValue sci_pause(types::typed_list &in, int _iRetCount, ty
 
     ConfigVariable::IncreasePauseLevel();
 
-    //unlock prompt thread.
-    ThreadManagement::SendAwakeRunnerSignal();
+    // unlock console thread to display prompt again
     ThreadManagement::SendConsoleExecDoneSignal();
 
-    types::ThreadId* pThread = ConfigVariable::getLastRunningThread();
-    if (pThread == NULL)
-    {
-        return types::Function::OK;
-    }
-
     //return to console so change mode to 2
     int iOldMode = ConfigVariable::getPromptMode();
     ConfigVariable::setPromptMode(2);
 
-    //suspend current thread
-    pThread->suspend();
-
-    // Running from here means we have been awaken by some resume / abort
-
-    //return from console so change mode to initial
-    ConfigVariable::setPromptMode(iOldMode);
-
-    ConfigVariable::DecreasePauseLevel();
-    if (pThread->getStatus() == types::ThreadId::Aborted)
+    int iPauseLevel = ConfigVariable::getPauseLevel();
+    while (ConfigVariable::getPauseLevel() == iPauseLevel)
     {
-        throw ast::InternalAbort();
+        ThreadManagement::SendAwakeRunnerSignal();
+        ThreadManagement::WaitForRunMeSignal();
+        StaticRunner_launch();
     }
 
+    //return from console so change mode to initial
+    ConfigVariable::setPromptMode(iOldMode);
     return types::Function::OK;
 }
index 773427f..44a3502 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
+ *  Copyright (C) 2015 - Scilab Enterprises - Cedric Delamarre
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
 types::Function::ReturnValue sci_quit(types::typed_list &in, int _iRetCount, types::typed_list &out)
 {
     //Terminates Scilab or decreases the pause level
-
-    types::ThreadId* pThreadId = ConfigVariable::getLastPausedThread();
-    if (pThreadId)
+    if (ConfigVariable::getPauseLevel())
     {
-        __threadId id = pThreadId->getThreadId();
-        pThreadId->abort();
-        __WaitThreadDie(id);
-
+        ConfigVariable::DecreasePauseLevel();
     }
     else
     {
         ConfigVariable::setForceQuit(true);
+        throw ast::InternalAbort();
     }
 
     return types::Function::OK;
index 606ce8a..7602a0f 100644 (file)
@@ -272,52 +272,45 @@ int StartScilabEngine(ScilabEngineInfo* _pSEI)
 
     ConfigVariable::setPromptMode(0);
     int iScript = 0;
-    try
+    if (_pSEI->pstExec)
     {
-        if (_pSEI->pstExec)
-        {
-            //-e option
-            Parser parser;
-            parseCommandTask(&parser, _pSEI->iTimed != 0, _pSEI->pstExec);
-
-            if (parser.getExitStatus() == Parser::Failed)
-            {
-                scilabWriteW(parser.getErrorMessage());
-            }
-            else if (parser.getControlStatus() !=  Parser::AllControlClosed)
-            {
-                _pSEI->iMultiLine = 1;
-            }
-            else
-            {
-                StoreConsoleCommand(_pSEI->pstExec);
-            }
+        //-e option
+        Parser parser;
+        parseCommandTask(&parser, _pSEI->iTimed != 0, _pSEI->pstExec);
 
-            if (parser.getTree())
-            {
-                delete parser.getTree();
-                parser.setTree(NULL);
-            }
-            iMainRet = ConfigVariable::getExitStatus();
-            iScript = 1;
+        if (parser.getExitStatus() == Parser::Failed)
+        {
+            scilabWriteW(parser.getErrorMessage());
+        }
+        else if (parser.getControlStatus() !=  Parser::AllControlClosed)
+        {
+            _pSEI->iMultiLine = 1;
         }
-        else if (_pSEI->pstFile)
+        else
+        {
+            StoreConsoleCommand(_pSEI->pstExec);
+        }
+
+        if (parser.getTree())
         {
-            //-f option execute exec('%s',-1)
-            char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
-            sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
-
-            StoreConsoleCommand(pstCommand);
-            FREE(pstCommand);
-            iMainRet = ConfigVariable::getExitStatus();
-            _pSEI->pstExec = NULL;
-            _pSEI->pstFile = NULL;
-            iScript = 1;
+            delete parser.getTree();
+            parser.setTree(NULL);
         }
+        iMainRet = ConfigVariable::getExitStatus();
+        iScript = 1;
     }
-    catch (const ast::ScilabException& se)
+    else if (_pSEI->pstFile)
     {
-        scilabErrorW(se.GetErrorMessage().c_str());
+        //-f option execute exec('%s',-1)
+        char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
+        sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
+
+        StoreConsoleCommand(pstCommand);
+        FREE(pstCommand);
+        iMainRet = ConfigVariable::getExitStatus();
+        _pSEI->pstExec = NULL;
+        _pSEI->pstFile = NULL;
+        iScript = 1;
     }
 
     ConfigVariable::setPromptMode(2);
@@ -732,11 +725,31 @@ static int interactiveMain(ScilabEngineInfo* _pSEI)
     // thread to manage command stored
     __CreateThreadWithParams(&threadIdCommand, &threadKeyCommand, &scilabReadAndExecCommand, _pSEI);
 
-    __WaitThreadDie(threadIdCommand);
+#ifdef DEBUG_THREAD
+    std::cout << std::endl << "------------ threads summary ------------" << std::endl;
+    std::cout << "Main Thread                       : " << __GetCurrentThreadKey() << std::endl;
+    if (_pSEI->iStartConsoleThread)
+    {
+        std::cout << "scilabReadAndStore Thread         : " << threadKeyConsole << std::endl;
+    }
+    std::cout << "scilabReadAndExecCommand Thread   : " << threadKeyCommand << std::endl;
+    std::cout << "-----------------------------------------" << std::endl;
+#endif // DEBUG_THREAD
 
-#ifdef DEBUG
-    std::cerr << "To end program press [ENTER]" << std::endl;
-#endif
+    do
+    {
+        ThreadManagement::WaitForRunMeSignal();
+        try
+        {
+            StaticRunner::launch();
+        }
+        catch (const ast::InternalAbort& /*ia*/)
+        {
+            // go out when exit/quit is called
+        }
+        ThreadManagement::SendAwakeRunnerSignal();
+    }
+    while (ConfigVariable::getForceQuit() == false);
 
     return ConfigVariable::getExitStatus();
 }
index 5d8e127..032cc17 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
+ *  Copyright (C) 2014-2015 - Scilab Enterprises - Cedric Delamarre
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
@@ -23,26 +24,21 @@ extern "C"
 
 using namespace ast;
 
-void *Runner::launch(void *args)
-{
-    bool bdoUnlock = false;
-    //try to lock locker ( waiting parent thread register me )
-    ThreadManagement::LockRunner();
-    //just release locker
-    ThreadManagement::UnlockRunner();
+Runner* StaticRunner::m_RunMe = NULL;
+bool StaticRunner::m_bInterruptibleCommand = true;
 
-    __threadKey currentThreadKey = __GetCurrentThreadKey();
-    ThreadId* pThread = ConfigVariable::getThread(currentThreadKey);
-
-    //exec !
-    Runner *me = (Runner *)args;
+void StaticRunner::launch()
+{
+    // get the runner to execute
+    Runner* runMe = getRunner();
+    // set if the current comment is interruptible
+    setInterruptibleCommand(runMe->isInterruptible());
 
     try
     {
-        me->getProgram()->accept(*(me->getVisitor()));
-        //ConfigVariable::clearLastError();
+        runMe->getProgram()->accept(*(runMe->getVisitor()));
     }
-    catch (const ast::ScilabException& se)
+    catch (const ast::InternalError& se)
     {
         scilabErrorW(se.GetErrorMessage().c_str());
         scilabErrorW(L"\n");
@@ -51,6 +47,28 @@ void *Runner::launch(void *args)
         scilabErrorW(ostr.str().c_str());
         ConfigVariable::resetWhereError();
     }
+    catch (const ast::InternalAbort& ia)
+    {
+        // management of pause
+        if (ConfigVariable::getPauseLevel())
+        {
+            ConfigVariable::DecreasePauseLevel();
+            throw ia;
+        }
+
+        // close all scope before return to console scope
+        symbol::Context* pCtx = symbol::Context::getInstance();
+        while (pCtx->getScopeLevel() != SCOPE_CONSOLE)
+        {
+            pCtx->scope_end();
+        }
+
+        // management of exit/quit
+        if (ConfigVariable::getForceQuit())
+        {
+            throw ia;
+        }
+    }
 
     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
     {
@@ -69,119 +87,96 @@ void *Runner::launch(void *args)
     // reset error state when new prompt occurs
     ConfigVariable::resetError();
 
-    //change thread status
-    if (pThread->getStatus() != ThreadId::Aborted)
-    {
-        pThread->setStatus(ThreadId::Done);
-        bdoUnlock = true;
-    }
-
-    ThreadManagement::LockAst();
-    if (pThread->getInterrupt()) // non-prioritary
-    {
-        // Unlock prioritary thread waiting for
-        // non-prioritary thread end this "SeqExp" execution.
-        // This case appear when error is throw or when
-        // non-prioritary execute this last SeqExp.
-        pThread->setInterrupt(false);
-        pThread->setInterruptible(false);
-        ThreadManagement::SendAstPendingSignal();
-    }
-    ThreadManagement::UnlockAst();
-
-    if (pThread->isConsoleCommand())
+    if (runMe->isConsoleCommand())
     {
         ThreadManagement::SendConsoleExecDoneSignal();
     }
 
-    //unregister thread
-    ConfigVariable::deleteThread(currentThreadKey);
+    delete runMe;
+}
 
-    delete me;
+void StaticRunner::setRunner(Runner* _RunMe)
+{
+    m_RunMe = _RunMe;
+}
 
-    if (bdoUnlock)
-    {
-        ThreadManagement::SendAwakeRunnerSignal();
-    }
+Runner* StaticRunner::getRunner(void)
+{
+    ThreadManagement::LockRunner();
+    Runner* tmp = m_RunMe;
+    m_RunMe = NULL;
+    ThreadManagement::UnlockRunner();
+    ThreadManagement::SendAvailableRunnerSignal();
+    return tmp;
+}
 
-    return NULL;
+bool StaticRunner::isRunnerAvailable(void)
+{
+    ThreadManagement::LockRunner();
+    bool bOut = m_RunMe != NULL;
+    ThreadManagement::UnlockRunner();
+    return bOut;
 }
 
-void Runner::execAndWait(ast::Exp* _theProgram, ast::ExecVisitor *_visitor,
-                         bool _isPrioritaryThread, bool _isInterruptibleThread, bool _isConsoleCommand)
+void StaticRunner::setInterruptibleCommand(bool _bInterruptibleCommand)
 {
-    try
-    {
-        Runner *runMe = new Runner(_theProgram, _visitor);
-        __threadKey threadKey;
-        __threadId threadId;
+    ThreadManagement::LockRunner();
+    m_bInterruptibleCommand = _bInterruptibleCommand;
+    ThreadManagement::UnlockRunner();
+}
 
-        types::ThreadId* pInterruptibleThread = ConfigVariable::getLastRunningThread();
-        if (_isPrioritaryThread)
-        {
-            if (pInterruptibleThread)
-            {
-                ThreadManagement::LockAst();
-                if (pInterruptibleThread->isInterruptible())
-                {
-                    pInterruptibleThread->setInterrupt(true);
-                    ThreadManagement::WaitForAstPendingSignal();
-                }
-                else
-                {
-                    ThreadManagement::UnlockAst();
-                    __WaitThreadDie(pInterruptibleThread->getThreadId());
-                    pInterruptibleThread = NULL;
-                }
-            }
-        }
-        else if (pInterruptibleThread)
-        {
-            __WaitThreadDie(pInterruptibleThread->getThreadId());
-            pInterruptibleThread = NULL;
-        }
+bool StaticRunner::isInterruptibleCommand()
+{
+    ThreadManagement::LockRunner();
+    bool bIsInterruptibleCommand = m_bInterruptibleCommand;
+    ThreadManagement::UnlockRunner();
+    return bIsInterruptibleCommand;
+}
 
-        // Lock the thread "Runner::launch" to be sure that all
-        // stuff performed before the "WaitForAwakeRunnerSignal"
-        // are done.
-        ThreadManagement::LockRunner();
+void StaticRunner::execAndWait(ast::Exp* _theProgram, ast::ExecVisitor *_visitor,
+                               bool _isPrioritaryThread, bool _isInterruptible, bool _isConsoleCommand)
+{
+    if (isRunnerAvailable())
+    {
+        // wait for managenement of last Runner
+        ThreadManagement::WaitForAvailableRunnerSignal();
+    }
 
-        //launch thread but is can't really start since locker is locked
-        __CreateThreadWithParams(&threadId, &threadKey, &Runner::launch, runMe);
-        runMe->setThreadId(threadId);
-        runMe->setThreadKey(threadKey);
+    // lock runner to be sure we are waiting for
+    // "AwakeRunner" signal before start execution
+    ThreadManagement::LockRunner();
+    Runner *runMe = new Runner(_theProgram, _visitor, _isConsoleCommand, _isInterruptible);
+    setRunner(runMe);
 
-        //register thread
-        types::ThreadId* pThread = new ThreadId(threadId, threadKey);
-        ConfigVariable::addThread(pThread);
-        pThread->setConsoleCommandFlag(_isConsoleCommand);
-        pThread->setInterruptible(_isInterruptibleThread);
+    ThreadManagement::SendRunMeSignal();
+    ThreadManagement::WaitForAwakeRunnerSignal();
+}
 
-        //free locker to release thread && wait and of thread execution
-        ThreadManagement::WaitForAwakeRunnerSignal();
+void StaticRunner::exec(ast::Exp* _theProgram, ast::ExecVisitor *_visitor)
+{
+    ThreadManagement::LockRunner();
+    Runner *runMe = new Runner(_theProgram, _visitor);
+    setRunner(runMe);
+    ThreadManagement::UnlockRunner();
+    launch();
+}
 
-        if (pInterruptibleThread && pInterruptibleThread->getInterrupt())
-        {
-            pInterruptibleThread->setInterrupt(false);
-            pInterruptibleThread->resume();
-        }
+void StaticRunner_launch(void)
+{
+    StaticRunner::launch();
+}
 
-        types::ThreadId* pExecThread = ConfigVariable::getThread(threadKey);
-        if (pExecThread == NULL)
-        {
-            //call pthread_join to clean stack allocation
-            __WaitThreadDie(threadId);
-        }
-    }
-    catch (const ast::ScilabException& se)
-    {
-        throw se;
-    }
+int StaticRunner_isRunnerAvailable(void)
+{
+    return StaticRunner::isRunnerAvailable() ? 1 : 0;
 }
 
-void Runner::exec(ast::Exp* _theProgram, ast::ExecVisitor *_visitor)
+int StaticRunner_isInterruptibleCommand(void)
 {
-    m_theProgram = _theProgram;
-    m_visitor = _visitor;
-    __CreateThreadWithParams(&m_threadId, &m_threadKey, &Runner::launch, this);
+    return StaticRunner::isInterruptibleCommand() ? 1 : 0;
 }
+
+void StaticRunner_setInterruptibleCommand(int val)
+{
+    StaticRunner::setInterruptibleCommand(val == 1);
+}
\ No newline at end of file
index 66c4aa3..e0c0006 100644 (file)
@@ -190,7 +190,7 @@ void execAstTask(ast::Exp* tree, bool serialize, bool timed, bool ASTtimed, bool
         exec = new ast::ExecVisitor();
     }
 
-    Runner::execAndWait(newTree, exec, isInterruptibleThread, isPrioritaryThread, isConsoleCommand);
+    StaticRunner::execAndWait(newTree, exec, isInterruptibleThread, isPrioritaryThread, isConsoleCommand);
     //DO NOT DELETE tree or newTree, they was deleted by Runner or previously;
 
     if (timed)
@@ -227,11 +227,10 @@ void execScilabStartTask(bool _bSerialize)
 {
     Parser parse;
     wstring stSCI = ConfigVariable::getSCIPath();
-
     stSCI += SCILAB_START;
+
     ThreadManagement::LockParser();
     parse.parseFile(stSCI, L"");
-
     if (parse.getExitStatus() != Parser::Succeded)
     {
         scilabWriteW(parse.getErrorMessage());
@@ -239,9 +238,14 @@ void execScilabStartTask(bool _bSerialize)
         ThreadManagement::UnlockParser();
         return;
     }
-
     ThreadManagement::UnlockParser();
-    execAstTask(parse.getTree(), _bSerialize, false, false, false, true, true, false);
+
+    ast::Exp* newTree = parse.getTree();
+    if (_bSerialize)
+    {
+        newTree = callTyper(parse.getTree());
+    }
+    StaticRunner::exec(newTree, new ast::ExecVisitor());
 }
 
 /*
@@ -252,11 +256,10 @@ void execScilabQuitTask(bool _bSerialize)
 {
     Parser parse;
     wstring stSCI = ConfigVariable::getSCIPath();
-
     stSCI += SCILAB_QUIT;
+
     ThreadManagement::LockParser();
     parse.parseFile(stSCI, L"");
-
     if (parse.getExitStatus() != Parser::Succeded)
     {
         scilabWriteW(parse.getErrorMessage());
@@ -264,9 +267,14 @@ void execScilabQuitTask(bool _bSerialize)
         ThreadManagement::UnlockParser();
         return;
     }
-
     ThreadManagement::UnlockParser();
-    execAstTask(parse.getTree(), _bSerialize, false, false, false, true, true, false);
+
+    ast::Exp* newTree = parse.getTree();
+    if (_bSerialize)
+    {
+        newTree = callTyper(parse.getTree());
+    }
+    StaticRunner::exec(newTree, new ast::ExecVisitor());
 }