75a87b9a30c7ac669d659f9a429d3592d450dd38
[scilab.git] / scilab / modules / core / src / cpp / runner.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include "runner.hxx"
14
15 __threadLock Runner::m_lock;
16 __threadSignal Runner::m_awakeScilab;
17 __threadSignalLock Runner::m_awakeScilabLock;
18
19 using namespace ast;
20
21 void Runner::init()
22 {
23     __InitSignal(&m_awakeScilab);
24     __InitSignalLock(&m_awakeScilabLock);
25 }
26
27 void *Runner::launch(void *args)
28 {
29     bool bdoUnlock = false;
30     //try to lock locker ( waiting parent thread register me )
31     __Lock(&m_lock);
32     //just release locker
33     __UnLock(&m_lock);
34
35     //exec !
36     Runner *me = (Runner *)args;
37     try
38     {
39         me->getProgram()->accept(*(me->getVisitor()));
40         //ConfigVariable::clearLastError();
41     }
42     catch (const ast::ScilabException& se)
43     {
44         scilabErrorW(se.GetErrorMessage().c_str());
45     }
46
47     // reset error state when new prompt occurs
48     ConfigVariable::resetError();
49
50     __threadKey currentThreadKey = __GetCurrentThreadKey();
51
52     //change thread status
53     ThreadId* pThread = ConfigVariable::getThread(currentThreadKey);
54     if (pThread->getStatus() != ThreadId::Aborted)
55     {
56         pThread->setStatus(ThreadId::Done);
57         bdoUnlock = true;
58     }
59
60     //unregister thread
61     ConfigVariable::deleteThread(currentThreadKey);
62
63     delete me;
64
65     if (bdoUnlock)
66     {
67         UnlockPrompt();
68     }
69     return NULL;
70 }
71
72 void Runner::LockPrompt()
73 {
74     __LockSignal(&m_awakeScilabLock);
75     //free locker to release thread
76     __UnLock(&m_lock);
77     __Wait(&m_awakeScilab, &m_awakeScilabLock);
78     __UnLockSignal(&m_awakeScilabLock);
79 }
80
81 void Runner::UnlockPrompt()
82 {
83     __LockSignal(&m_awakeScilabLock);
84     __Signal(&m_awakeScilab);
85     __UnLockSignal(&m_awakeScilabLock);
86 }
87
88
89 void Runner::execAndWait(ast::Exp* _theProgram, ast::ExecVisitor *_visitor)
90 {
91     try
92     {
93         Runner *runMe = new Runner(_theProgram, _visitor);
94         __threadKey threadKey;
95         __threadId threadId;
96
97         //init locker
98         __InitLock(&m_lock);
99         //lock locker
100         __Lock(&m_lock);
101         //launch thread but is can't really start since locker is locked
102         __CreateThreadWithParams(&threadId, &threadKey, &Runner::launch, runMe);
103         runMe->setThreadId(threadId);
104         runMe->setThreadKey(threadKey);
105
106         //register thread
107         ConfigVariable::addThread(new ThreadId(threadId, threadKey));
108         //free locker to release thread && wait and of thread execution
109         LockPrompt();
110
111         types::ThreadId* pExecThread = ConfigVariable::getThread(threadKey);
112         if (pExecThread == NULL)
113         {
114             //call pthread_join to clean stack allocation
115             __WaitThreadDie(threadId);
116         }
117     }
118     catch (const ast::ScilabException& se)
119     {
120         throw se;
121     }
122 }
123
124 void Runner::exec(ast::Exp* _theProgram, ast::ExecVisitor *_visitor)
125 {
126     m_theProgram = _theProgram;
127     m_visitor = _visitor;
128     __CreateThreadWithParams(&m_threadId, &m_threadKey, &Runner::launch, this);
129 }