2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
4 * Copyright (C) 2014-2015 - Scilab Enterprises - Cedric Delamarre
6 * Copyright (C) 2012 - 2016 - Scilab Enterprises
8 * This file is hereby licensed under the terms of the GNU GPL v2.0,
9 * pursuant to article 5.3.4 of the CeCILL v.2.1.
10 * This file was originally licensed under the terms of the CeCILL v2.1,
11 * and continues to be available under such terms.
12 * For more information, see the COPYING file which you should have received
13 * along with this program.
18 #include "threadmanagement.hxx"
19 #include "configvariable.hxx"
20 #include "debugmanager.hxx"
24 #include "HistoryManager.h"
25 #include "BrowseVarManager.h"
26 #include "FileBrowserChDir.h"
27 #include "scicurdir.h"
29 #include "InitializeJVM.h"
32 std::atomic<Runner*> StaticRunner::m_RunMe(nullptr);
33 std::atomic<Runner*> StaticRunner::m_CurrentRunner(nullptr);
35 static bool initialJavaHooks = false;
37 void StaticRunner::sendExecDoneSignal()
39 switch (m_CurrentRunner.load()->getCommandOrigin())
43 ThreadManagement::SendDebuggerExecDoneSignal();
48 ThreadManagement::SendConsoleExecDoneSignal();
57 int StaticRunner::launch()
59 //set execution thread in java
60 if (!initialJavaHooks && getScilabMode() != SCILAB_NWNI)
62 initialJavaHooks = true;
63 // Execute the initial hooks registered in Scilab.java
64 ExecuteInitialHooks();
69 // save current runner
70 Runner* pRunSave = m_CurrentRunner.load();
72 // get the runner to execute
73 std::unique_ptr<Runner> runMe(getRunner());
75 debugger::DebuggerManager* manager = debugger::DebuggerManager::getInstance();
76 manager->resetAborted();
78 ConfigVariable::resetExecutionBreak();
80 int oldMode = ConfigVariable::getPromptMode();
81 symbol::Context* pCtx = symbol::Context::getInstance();
82 int scope = pCtx->getScopeLevel();
84 // a TCL command display nothing
85 int iOldPromptMode = 0;
86 if (runMe->getCommandOrigin() == TCLSCI)
88 iOldPromptMode = ConfigVariable::getPromptMode();
89 ConfigVariable::setPromptMode(-1);
94 int level = ConfigVariable::getRecursionLevel();
97 runMe->getProgram()->accept(*(runMe->getVisitor()));
99 catch (const ast::RecursionException& re)
101 // management of pause
102 if (ConfigVariable::getPauseLevel())
104 ConfigVariable::DecreasePauseLevel();
108 //close opened scope during try
109 while (pCtx->getScopeLevel() > scope)
114 //decrease recursion to init value and close where
115 while (ConfigVariable::getRecursionLevel() > level)
117 ConfigVariable::where_end();
118 ConfigVariable::decreaseRecursion();
121 ConfigVariable::resetWhereError();
122 ConfigVariable::setPromptMode(oldMode);
124 //print msg about recursion limit and trigger an error
126 os_swprintf(sz, 1024, _W("Recursion limit reached (%d).\n").data(), ConfigVariable::getRecursionLimit());
127 throw ast::InternalError(sz);
130 catch (const ast::InternalError& se)
132 if (runMe->getCommandOrigin() == TCLSCI)
134 ConfigVariable::setPromptMode(iOldPromptMode);
137 std::wostringstream ostr;
138 ConfigVariable::whereErrorToString(ostr);
139 scilabErrorW(ostr.str().c_str());
140 scilabErrorW(se.GetErrorMessage().c_str());
141 ConfigVariable::resetWhereError();
144 catch (const ast::InternalAbort& ia)
146 if (runMe->getCommandOrigin() == TCLSCI)
148 ConfigVariable::setPromptMode(iOldPromptMode);
151 // management of pause
152 if (ConfigVariable::getPauseLevel())
154 ConfigVariable::DecreasePauseLevel();
155 // set back the runner wich have been overwritten in StaticRunner::getRunner
156 m_CurrentRunner.store(pRunSave);
160 // close all scope before return to console scope
161 symbol::Context* pCtx = symbol::Context::getInstance();
162 while (pCtx->getScopeLevel() > scope)
167 // debugger leave with abort state
168 manager->setAborted();
170 // send the good signal about the end of execution
171 sendExecDoneSignal();
173 // set back the runner wich have been overwritten in StaticRunner::getRunner
174 m_CurrentRunner.store(pRunSave);
178 if (runMe->getCommandOrigin() == TCLSCI)
180 ConfigVariable::setPromptMode(iOldPromptMode);
183 if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
189 saveScilabHistoryToFile();
190 cwd = scigetcwd(&err);
193 FileBrowserChDir(cwd);
198 // reset error state when new prompt occurs
199 ConfigVariable::resetError();
201 // send the good signal about the end of execution
202 sendExecDoneSignal();
204 //clean debugger step flag if debugger is not interrupted ( end of debug )
205 manager->resetStep();
207 // set back the runner wich have been overwritten in StaticRunner::getRunner
208 m_CurrentRunner.store(pRunSave);
213 void StaticRunner::setRunner(Runner* _RunMe)
218 Runner* StaticRunner::getRunner(void)
220 m_CurrentRunner.store(m_RunMe.exchange(nullptr));
221 ThreadManagement::SendAvailableRunnerSignal();
222 return m_CurrentRunner.load();
225 // return true if a Runner is already set in m_RunMe.
226 bool StaticRunner::isRunnerAvailable(void)
228 return m_RunMe.load() != nullptr;
231 // return true if a command is running or paused.
232 bool StaticRunner::isRunning(void)
234 return m_CurrentRunner.load() != nullptr;
237 bool StaticRunner::isInterruptibleCommand()
239 return m_CurrentRunner.load()->isInterruptible();
242 command_origin_t StaticRunner::getCommandOrigin()
244 return m_RunMe.load()->getCommandOrigin();
247 void StaticRunner::setCommandOrigin(command_origin_t _origin)
249 m_CurrentRunner.load()->setCommandOrigin(_origin);
252 void StaticRunner::execAndWait(ast::Exp* _theProgram, ast::RunVisitor *_visitor,
253 bool /*_isPrioritaryThread*/, bool _isInterruptible, command_origin_t _iCommandOrigin)
255 if (isRunnerAvailable())
257 // wait for managenement of last Runner
258 ThreadManagement::WaitForAvailableRunnerSignal();
261 // lock runner to be sure we are waiting for
262 // "AwakeRunner" signal before start execution
263 ThreadManagement::LockRunner();
264 Runner *runMe = new Runner(_theProgram, _visitor, _iCommandOrigin, _isInterruptible);
267 ThreadManagement::SendRunMeSignal();
268 ThreadManagement::WaitForAwakeRunnerSignal();
271 bool StaticRunner::exec(ast::Exp* _theProgram, ast::RunVisitor *_visitor)
273 Runner *runMe = new Runner(_theProgram, _visitor);
280 catch (const ast::InternalAbort& /*ia*/)
282 //catch exit command in .start or .quit
289 void StaticRunner_launch(void)
291 StaticRunner::launch();
294 int StaticRunner_isRunning(void)
296 return StaticRunner::isRunning() ? 1 : 0;
299 int StaticRunner_isRunnerAvailable(void)
301 return StaticRunner::isRunnerAvailable() ? 1 : 0;
304 int StaticRunner_isInterruptibleCommand(void)
306 return StaticRunner::isInterruptibleCommand() ? 1 : 0;
309 command_origin_t StaticRunner_getCommandOrigin(void)
311 return StaticRunner::getCommandOrigin();
314 void StaticRunner_setCommandOrigin(command_origin_t _origin)
316 StaticRunner::setCommandOrigin(_origin);