root/simulator/trunk/src/simulator/task.cpp

Revision 1449, 14.5 kB (checked in by sehenley, 7 months ago)

Clean tabs, line endings - etc.

  • Property WBS set to 1.1.4.11
  • Property svn:keywords set to
    Url
    Rev
    Author
    Date
    Id
Line 
1 //    OSRail -- a network enabled railroad operations simulator and utilities
2 //    Copyright (C) 2007,2008 Samuel E. Henley sehenley@comcast.net
3 //
4 //    This program is free software; you can redistribute it and/or modify
5 //    it under the terms of the GNU General Public License as published by
6 //    the Free Software Foundation; either version 2 of the License, or
7 //    (at your option) any later version.
8 //
9 //    This program is distributed in the hope that it will be useful,
10 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //    GNU General Public License for more details.
13 //
14 //    You should have received a copy of the GNU General Public License along
15 //    with this program; if not, write to the Free Software Foundation, Inc.,
16 //    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 //
18 /// \file
19 /// Implementation file for Task manager of the simulator and the ITask factory.
20
21 // Pre-Compiled Header for Simulator
22 #include "presimulator.h"
23
24 #include "task.h"
25
26
27 /// \addtogroup simulator "Simulator"
28 /// @{
29     /// \addtogroup simulatorcomponent "Simulator Components"
30     /// @{
31         /// \addtogroup task "Task"
32         /// @{
33
34
35 extern ITask* createTask( ISystem& sys )
36 {
37     return new Task( sys );
38 }
39
40 Task::Task( ISystem& sys ) : system( sys ), engine(0)
41 {
42 }
43
44 Task::~Task()
45 {
46 }
47
48
49
50 //vertual
51 void Task::startup()
52 {
53     MESSAGE( "Simulator", "Task", "Startup" )
54     error.resize( 1024 ); //Common error buffer
55     configureScriptEngine();
56 }
57
58 //virtual
59 void Task::operator()()
60 {
61     if( compiles.empty() )
62     {
63         if( !scripts.empty() )
64         {
65             int id = scripts.top().context->GetCurrentFunction();
66             const_cast<Script&>(scripts.top()).timeout = scripts.top().max + system.getFrameMilliseconds();
67             scripts.top().context->SetLineCallback( asFUNCTION(taskLineCallback), this, asCALL_CDECL );
68             scripts.top().context->SetExceptionCallback( asFUNCTION(taskExceptionCallback), this, asCALL_CDECL );
69
70             int result = scripts.top().context->Execute();
71             if( result < 0 )
72             {
73                 asIScriptFunction* fd = engine->GetFunctionDescriptorById( id );
74                 sprintf( &error[0], "Could not execute function %s", fd->GetName() );
75                 ASSERT( false, "Simulator", "Task", &error[0] )
76                 scripts.top().context->Release();
77                 scripts.pop();
78             }
79             else
80             {
81                 switch( result )
82                 {
83                 case asEXECUTION_SUSPENDED :
84                     break;
85
86                 case asEXECUTION_ABORTED :
87                 case asEXECUTION_EXCEPTION :
88                 case asEXECUTION_FINISHED :
89                     scripts.top().context->Release();
90                     scripts.pop();
91                     break;
92
93                 default:
94                     {
95                         asIScriptFunction* fd = engine->GetFunctionDescriptorById( id );
96                         sprintf( &error[0], "Program logic error, result from AngelScript Execute unrecognized module %s", fd->GetModuleName() );
97                         ASSERT( false, "ScriptManager", "Task", &error[0] )
98                     }
99                     break;
100                 }
101             }
102         }
103     }
104     else
105     {
106         const Compile& it = compiles.top();
107         asIScriptModule* module = engine->GetModule( it.module.c_str(), asGM_ALWAYS_CREATE );
108         module->AddScriptSection( "script", it.script.c_str(), it.script.length(), 0 );
109         if( module->Build() < 0 )
110         {
111             sprintf( &error[0], "Did not create script context for script module %s", it.module.c_str());
112             ASSERT( false, "Simulator", "Task", &error[0] )
113         }
114         else
115         {
116             size_t size = module->GetFunctionCount();
117             for( size_t i=0; i<size; i++ )
118             {
119                 asIScriptContext* context = engine->CreateContext();
120                 if( !context )
121                 {
122                     sprintf( &error[0], "Could not create context for script module %s", it.module.c_str());
123                     ASSERT( false, "ScriptManager", "Task", &error[0] )
124                 }
125
126                 int id = module->GetFunctionIdByIndex( i );
127                 if( context->Prepare( id ) < 0 )
128                 {
129                     sprintf( &error[0], "Could not Prepare context for script module %s", it.module.c_str());
130                     ASSERT( false, "ScriptManager", "Task", &error[0] )
131                     context->Release();
132                 }
133                 else
134                 {
135                     Script ss;
136                     ss.context = context;
137                     ss.priority = it.priority;
138                     ss.context->SetUserData( reinterpret_cast<void*>(this) );
139                     ss.max = it.max;
140                     ss.timeout = 0;
141                     scripts.push( ss );
142                 }
143             }
144         }
145
146         compiles.pop();
147     }
148 }
149
150 //virtual
151 void Task::shutdown()
152 {
153     while( !scripts.empty() )
154     {
155         scripts.top().context->Release();
156         scripts.pop();
157     }
158     if( engine )engine->Release();
159     engine = 0;
160     MESSAGE( "Simulator", "Task", "Cleanup scripts" )
161     MESSAGE( "Simulator", "Task", "Shutdown" )
162 }
163
164 //virtual
165 bool Task::addScript( const char* module, const char* script, const clock_t max /*= 10*/, const int priority /*= 0*/ )
166 {
167     ASSERT( engine != 0, "ScriptManager", "Task", "addScript called with no script engine" )
168     Compile cc;
169     cc.module = module;
170     cc.script = script;
171     cc.max = max;
172     compiles.push( cc );
173
174     return true;
175 }
176
177 //static
178 void Task::taskMessageCallback( const asSMessageInfo* msg, void* param )
179 {
180     /// \todo Move script error to Console, or logger.
181     String type;
182     switch( msg->type )
183     {
184     case asMSGTYPE_ERROR :         type = _(" error="); break;
185     case asMSGTYPE_WARNING :       type = _(" warning="); break;
186     case asMSGTYPE_INFORMATION :   type = _(" information=");break;
187     default : type = _("?");
188         ASSERT( false, "Simulator", "Task", "Program error AngelScript message type" ) // How did we get here?
189     }
190
191     std::vector<char> error;
192     error.resize( 1024 );
193     sprintf( &error[0], "%s row=%d col=%d %s %s",
194              msg->section,
195              msg->row,
196              msg->col,
197              type.c_str(),
198              msg->message );
199
200     MESSAGE( "Simulator", "Task", &error[0] )
201 }
202
203 void Task::taskTimeout( asIScriptContext* context )
204 {
205     if( scripts.top().timeout < system.getFrameMilliseconds() )
206     {
207         context->Suspend();
208     }
209 }
210
211 void Task::taskException( asIScriptContext* context )
212 {
213     context->Suspend();
214     int id = context->GetCurrentFunction();
215     asIScriptFunction* fd = engine->GetFunctionDescriptorById( id );
216     sprintf( &error[0], "Exception in function %s", fd->GetName() );
217     ASSERT( false, "Simulator", "Task", &error[0] )
218     scripts.top().context->Release();
219     scripts.pop();
220 }
221
222 //static
223 void Task::taskLineCallback( asIScriptContext* context, asDWORD* task )
224 {
225     ASSERT( task, "Simulator", "Task", "Programing error callback Task::taskLineCallback has no object pointer" )
226     (reinterpret_cast<Task*>(task))->taskTimeout( context );
227 }
228
229 //static
230 void Task::taskExceptionCallback( asIScriptContext* context, asDWORD* task )
231 {
232     ASSERT( task, "Simulator", "Task", "Script error callback Task::taskExceptionCallback called" )
233     (reinterpret_cast<Task*>(task))->taskException( context );
234 }
235
236 /// \note Script interfaces to simulator
237 IAi*               g_ai = 0;
238 IConsoleClient*    g_console = 0;
239 IFactory*          g_factory = 0;
240 IGraphics*         g_graphics = 0;
241 IGui*              g_gui = 0;
242 IInput*            g_input = 0;
243 INetwork*          g_network = 0;
244 IPropertyManager*  g_propertymanager = 0;
245 ISimulation*       g_simulation = 0;
246 ISound*            g_sound = 0;
247 ISystem*           g_system = 0;
248 ITask*             g_task = 0;
249 ITest*             g_test = 0;
250
251
252 /// Wrapper for ITask::addScript
253 bool ITask_addScript_Wrapper( CScriptString& name, CScriptString& script, const int max, const int priority, ITask* task )
254 {
255     return task->addScript( name.buffer.c_str(), script.buffer.c_str(), max, priority );
256 }
257
258 //private
259 void Task::configureScriptEngine()
260 {
261     // initialize system interfaces, must initialize ITask last in ISystem startup.
262     g_ai = system.getAiInterface();
263     g_console = system.getConsoleClientInterface();
264     g_factory = system.getFactoryInterface();
265     g_graphics = system.getGraphicsInterface();
266     g_gui = system.getGuiInterface();
267     g_input = system.getInputInterface();
268     g_network = system.getNetworkInterface();
269     g_propertymanager = system.getPropertyManagerInterface();
270     g_simulation = system.getSimulationInterface();
271     g_sound = system.getSoundInterface();
272     g_system = system.getSystemInterface();
273     g_task = system.getTaskInterface();
274     g_test = system.getTestInterface();
275
276     ASSERT( engine == 0, "Simulator", "Task", "Program error AngelScript engine already created" )
277     engine = asCreateScriptEngine( ANGELSCRIPT_VERSION );
278     ASSERT( engine, "Simulator", "Task", "Could not create AngelScript engine" )
279     engine->SetMessageCallback( asFUNCTION(taskMessageCallback), 0, asCALL_CDECL );
280     MESSAGE( "Simulator", "Task", "Initialized scripts" )
281
282     RegisterScriptString( engine );
283
284     // ISystem
285     VERIFY(( engine->RegisterObjectType("ISystem", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register ISystem interface" )
286     VERIFY(( engine->RegisterObjectMethod( "ISystem", "bool running()", asMETHOD( ISystem, running ), asCALL_THISCALL ) >= 0 ),
287             "Simulator", "Task", "Could not register ISystem::running interface" )
288     VERIFY(( engine->RegisterGlobalProperty( "ISystem system",  &g_system ) >= 0 ),  "Simulator", "Task", "Unable add properity system to AngelScript Engine" )
289
290     VERIFY(( engine->RegisterObjectType("IGraphics", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register IGraphics interface" )
291     VERIFY(( engine->RegisterObjectMethod( "IGraphics", "bool isClosed()", asMETHOD( IGraphics, isClosed ), asCALL_THISCALL ) >= 0 ),
292             "Simulator", "Task", "Could not register IGraphics::isClosed interface" )
293     VERIFY(( engine->RegisterObjectMethod( "IGraphics", "bool isVisible()", asMETHOD( IGraphics, isVisible ), asCALL_THISCALL ) >= 0 ),
294             "Simulator", "Task", "Could not register IGraphics::isVisible interface" )
295     VERIFY(( engine->RegisterGlobalProperty( "IGraphics graphics",  &g_graphics ) >= 0 ), "Simulator", "Task", "Unable add properity graphics to AngelScript Engine" )
296
297     // ITask
298     VERIFY(( engine->RegisterObjectType( "ITask", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register ITask interface" )
299     VERIFY(( engine->RegisterObjectMethod( "ITask", "bool addScript( const string &in name, const string &in script, const int &in max, const int &in priority )",
300             asFUNCTION( ITask_addScript_Wrapper ), asCALL_CDECL_OBJLAST ) >= 0 ),
301             "Simulator", "Task", "Could not register ITask::addScript (ITask_addScript_Wrapper) interface" )
302     VERIFY(( engine->RegisterGlobalProperty( "ITask task",  &g_task ) >= 0 ), "Simulator", "Task", "Unable add properity task to AngelScript Engine" )
303
304     // ISound
305     VERIFY(( engine->RegisterObjectType("ISound", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register ISound interface" )
306     VERIFY(( engine->RegisterGlobalProperty( "ISound sound",  &g_sound ) >= 0 ), "Simulator", "Task", "Unable add properity sound to AngelScript Engine" )
307
308     // IAi
309     VERIFY(( engine->RegisterObjectType("IAi", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register IAi interface" )
310     VERIFY(( engine->RegisterGlobalProperty( "IAi ai",  &g_ai ) >= 0 ), "Simulator", "Task", "Unable add properity ai to AngelScript Engine" )
311
312     // IInput
313     VERIFY(( engine->RegisterObjectType("IInput", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register IInput interface" )
314     VERIFY(( engine->RegisterGlobalProperty( "IInput input",  &g_input ) >= 0 ), "Simulator", "Task", "Unable add properity input to AngelScript Engine" )
315
316     // IGui
317     VERIFY(( engine->RegisterObjectType("IGui", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register IGui interface" )
318     VERIFY(( engine->RegisterGlobalProperty( "IGui gui",  &g_gui ) >= 0 ), "Simulator", "Task", "Unable add properity gui to AngelScript Engine" )
319
320     // INetwork
321     VERIFY(( engine->RegisterObjectType("INetwork", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register INetwork interface" )
322     VERIFY(( engine->RegisterGlobalProperty( "INetwork network",  &g_network ) >= 0 ), "Simulator", "Task", "Unable add properity network to AngelScript Engine" )
323
324     // IConsoleClient
325     VERIFY(( engine->RegisterObjectType("IConsoleClient", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ),
326             "Simulator", "Task", "Could not register IConsoleClient interface" )
327     VERIFY(( engine->RegisterGlobalProperty( "IConsoleClient consoleclient",  &g_console ) >= 0 ), "Simulator", "Task", "Unable add properity consoleclient to AngelScript Engine" )
328
329     // IFactory
330     VERIFY(( engine->RegisterObjectType("IFactory", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register IFactory interface" )
331     VERIFY(( engine->RegisterGlobalProperty( "IFactory factory",  &g_factory ) >= 0 ), "Simulator", "Task", "Unable add properity factory to AngelScript Engine" )
332
333     // IProperityManager
334     VERIFY(( engine->RegisterObjectType("IPropertyManager", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ),
335             "Simulator", "Task", "Could not register IPropertyManager interface" )
336     VERIFY(( engine->RegisterGlobalProperty( "IPropertyManager propertymanager",  &g_propertymanager ) >= 0 ), "Simulator", "Task", "Unable add properity propertymanager to AngelScript Engine" )
337
338     // ISimulation
339     VERIFY(( engine->RegisterObjectType("ISimulation", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register ISimulation interface" )
340     VERIFY(( engine->RegisterGlobalProperty( "ISimulation simulation",  &g_simulation ) >= 0 ), "Simulator", "Task", "Unable add properity simulation to AngelScript Engine" )
341
342     // Test
343     VERIFY(( engine->RegisterObjectType("ITest", 0, asOBJ_REF|asOBJ_NOHANDLE ) >= 0 ), "Simulator", "Task", "Could not register ITest interface" )
344     VERIFY(( engine->RegisterGlobalProperty( "ITest test",  &g_test ) >= 0 ), "Simulator", "Task", "Unable add properity test to AngelScript Engine" )
345
346
347 }
348
349
350
351
352
353          /// @}   group task
354     /// @}   group simulatorcomponent
355 /// @} group simulator
Note: See TracBrowser for help on using the browser.