1
0
forked from 0ad/0ad

Delete script scheduler, since it causes GC crashes and isn't used for anything important and could be implemented in pure JS instead.

This was SVN commit r7622.
This commit is contained in:
Ykkrosh 2010-06-07 18:41:03 +00:00
parent 5c9d0c17e2
commit 2c160e5bd8
7 changed files with 6 additions and 507 deletions

View File

@ -28,8 +28,8 @@
size="5 5 200 35"
z="199"
>
<action on="Load"><![CDATA[
setInterval (updateFPS, 1, 200);
<action on="Tick"><![CDATA[
updateFPS();
]]></action>
<action on="Press"><![CDATA[
this.hidden = !this.hidden;

View File

@ -60,7 +60,6 @@ that of Atlas depending on commandline parameters.
#include "network/NetSession.h"
#include "graphics/Camera.h"
#include "graphics/GameView.h"
#include "scripting/Scheduler.h"
#include "simulation2/Simulation2.h"
#include "sound/CMusicPlayer.h"
#include "gui/GUIManager.h"
@ -324,10 +323,6 @@ static void Frame()
}
else
{
// CSimulation would do this with the proper turn length if we were in
// a game. This is basically just to keep script timers running.
int ms_elapsed = (int)(TimeSinceLastFrame*1000);
g_Scheduler.Update(ms_elapsed);
if(snd_update(0, 0, 0) < 0)
debug_printf(L"snd_update (pos=0 version) failed\n");
}

View File

@ -69,7 +69,6 @@
#include "scripting/ScriptGlue.h"
#include "scripting/DOMEvent.h"
#include "scripting/ScriptableComplex.h"
#include "scripting/Scheduler.h"
#include "maths/scripting/JSInterface_Vector3D.h"
@ -338,9 +337,6 @@ static void InitScripting()
// [7ms]
new ScriptingHost;
// It would be nice for onLoad code to be able to access the setTimeout() calls.
new CScheduler;
RegisterJavascriptInterfaces();
#define REG_JS_CONSTANT(_name) g_ScriptingHost.DefineConstant(#_name, _name)
@ -586,10 +582,6 @@ void Shutdown(int flags)
ShutdownPs(); // Must delete g_GUI before g_ScriptingHost
TIMER_BEGIN(L"shutdown Scheduler");
delete &g_Scheduler;
TIMER_END(L"shutdown Scheduler");
if (! (flags & INIT_NO_SIM))
{
delete &g_GameAttributes;

View File

@ -1,211 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "Scheduler.h"
int simulationTime;
int frameCount;
CScheduler::CScheduler()
{
m_nextTaskId = 1;
}
int CScheduler::PushTime( int delay, const CStrW& fragment, JSObject* operateOn )
{
timeScript.push( SDispatchObjectScript( m_nextTaskId, fragment, simulationTime + delay, operateOn ) );
return m_nextTaskId++;
}
int CScheduler::PushFrame( int delay, const CStrW& fragment, JSObject* operateOn )
{
frameScript.push( SDispatchObjectScript( m_nextTaskId, fragment, frameCount + delay, operateOn ) );
return m_nextTaskId++;
}
int CScheduler::PushInterval( int first, int interval, const CStrW& fragment, JSObject* operateOn, int id )
{
if( !id )
id = m_nextTaskId++;
timeScript.push( SDispatchObjectScript( id, fragment, simulationTime + first, operateOn, interval ) );
return id++;
}
int CScheduler::PushTime( int delay, JSFunction* script, JSObject* operateOn )
{
timeFunction.push( SDispatchObjectFunction( m_nextTaskId, script, simulationTime + delay, operateOn ) );
return m_nextTaskId++;
}
int CScheduler::PushFrame( int delay, JSFunction* script, JSObject* operateOn )
{
frameFunction.push( SDispatchObjectFunction( m_nextTaskId, script, frameCount + delay, operateOn ) );
return m_nextTaskId++;
}
int CScheduler::PushInterval( int first, int interval, JSFunction* function, JSObject* operateOn, int id )
{
if( !id )
id = m_nextTaskId++;
timeFunction.push( SDispatchObjectFunction( id, function, simulationTime + first, operateOn, interval ) );
return id++;
}
void CScheduler::PushProgressTimer( CJSProgressTimer* progressTimer )
{
progressTimers.push_back( progressTimer );
}
void CScheduler::CancelTask( int id )
{
tasksToCancel.insert( id );
}
void CScheduler::Update(int simElapsed)
{
simulationTime += simElapsed;
frameCount++;
jsval rval;
while( !timeScript.empty() )
{
SDispatchObjectScript top = timeScript.top();
if( top.deliveryTime > simulationTime )
break;
timeScript.pop();
m_abortInterval = false;
if( tasksToCancel.find( top.id ) != tasksToCancel.end() )
{
tasksToCancel.erase( top.id );
continue;
}
g_ScriptingHost.ExecuteScript( top.script, L"timer", top.operateOn );
if( top.isRecurrent && !m_abortInterval )
PushInterval( top.delay, top.delay, top.script, top.operateOn, top.id );
}
while( !frameScript.empty() )
{
SDispatchObjectScript top = frameScript.top();
if( top.deliveryTime > frameCount )
break;
frameScript.pop();
if( tasksToCancel.find( top.id ) != tasksToCancel.end() )
{
tasksToCancel.erase( top.id );
continue;
}
g_ScriptingHost.ExecuteScript( top.script, L"timer", top.operateOn );
}
while( !timeFunction.empty() )
{
SDispatchObjectFunction top = timeFunction.top();
if( top.deliveryTime > simulationTime )
break;
timeFunction.pop();
m_abortInterval = false;
if( tasksToCancel.find( top.id ) != tasksToCancel.end() )
{
tasksToCancel.erase( top.id );
continue;
}
JS_CallFunction( g_ScriptingHost.getContext(), top.operateOn, top.function, 0, NULL, &rval );
if( top.isRecurrent && !m_abortInterval )
PushInterval( top.delay, top.delay, top.function, top.operateOn, top.id );
}
while( !frameFunction.empty() )
{
SDispatchObjectFunction top = frameFunction.top();
if( top.deliveryTime > frameCount )
break;
frameFunction.pop();
if( tasksToCancel.find( top.id ) != tasksToCancel.end() )
{
tasksToCancel.erase( top.id );
continue;
}
JS_CallFunction( g_ScriptingHost.getContext(), top.operateOn, top.function, 0, NULL, &rval );
}
std::list<CJSProgressTimer*>::iterator it;
for( it = progressTimers.begin(); it != progressTimers.end(); it++ )
{
(*it)->m_Current += (*it)->m_Increment * simElapsed;
if( (*it)->m_Current >= (*it)->m_Max )
{
(*it)->m_Current = (*it)->m_Max;
if( (*it)->m_Callback )
JS_CallFunction( g_ScriptingHost.GetContext(), (*it)->m_OperateOn, (*it)->m_Callback, 0, NULL, &rval );
it = progressTimers.erase( it );
}
}
}
CJSProgressTimer::CJSProgressTimer( double Max, double Increment, JSFunction* Callback, JSObject* OperateOn )
{
m_Max = Max; m_Increment = Increment; m_Callback = Callback; m_OperateOn = OperateOn; m_Current = 0.0;
}
void CJSProgressTimer::ScriptingInit()
{
AddProperty( L"max", &CJSProgressTimer::m_Max );
AddProperty( L"current", &CJSProgressTimer::m_Current );
AddProperty( L"increment", &CJSProgressTimer::m_Increment );
CJSObject<CJSProgressTimer>::ScriptingInit( "ProgressTimer", Construct, 2 );
}
JSBool CJSProgressTimer::Construct( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval )
{
debug_assert( argc >= 2 );
double max = ToPrimitive<double>( argv[0] );
double increment = ToPrimitive<double>( argv[1] );
JSFunction* callback_fn = NULL;
JSObject* scope_obj = NULL;
if( argc >= 3 )
{
callback_fn = JS_ValueToFunction( cx, argv[2] );
if( ( argc >= 4 ) && JSVAL_IS_OBJECT( argv[3] ) )
{
scope_obj = JSVAL_TO_OBJECT( argv[3] );
}
else
{
// Attempt to determine object to operate on automatically.
// SpiderMonkey docs say the 'this' parameter of the calling
// function is in argv[-2]. Do I believe them? One way to find out.
scope_obj = JSVAL_TO_OBJECT( argv[-2] );
}
}
CJSProgressTimer* timer = new CJSProgressTimer( max, increment, callback_fn, scope_obj );
timer->m_EngineOwned = false;
g_Scheduler.PushProgressTimer( timer );
*rval = OBJECT_TO_JSVAL( timer->GetScript() );
return( JS_TRUE );
}

View File

@ -1,113 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
// Scheduler.h
//
// Message scheduler
//
#ifndef INCLUDED_SCHEDULER
#define INCLUDED_SCHEDULER
#include <queue>
#include <list>
#include <set>
#include "ps/Singleton.h"
#include "ps/CStr.h"
#include "scripting/ScriptableObject.h"
class CJSProgressTimer;
// Message, destination and delivery time information.
struct SDispatchObject
{
int id;
int deliveryTime;
bool isRecurrent; int delay;
SDispatchObject( int _id, const int _deliveryTime )
: id(_id), deliveryTime( _deliveryTime ), isRecurrent( false ) {}
SDispatchObject( int _id, const int _deliveryTime, const int _recurrence )
: id(_id), deliveryTime( _deliveryTime ), isRecurrent( true ), delay( _recurrence ) {}
inline bool operator<( const SDispatchObject& compare ) const
{
return( deliveryTime > compare.deliveryTime );
}
};
struct SDispatchObjectScript : public SDispatchObject
{
CStrW script;
JSObject* operateOn;
inline SDispatchObjectScript( int _id, const CStrW& _script,
const int _deliveryTime, JSObject* _operateOn = NULL )
: SDispatchObject( _id, _deliveryTime ), script( _script ), operateOn( _operateOn ) {}
inline SDispatchObjectScript( int _id, const CStrW& _script,
const int _deliveryTime, JSObject* _operateOn, const int recurrence )
: SDispatchObject( _id, _deliveryTime, recurrence ), script( _script ), operateOn( _operateOn ) {}
};
struct SDispatchObjectFunction : public SDispatchObject
{
JSFunction* function;
JSObject* operateOn;
inline SDispatchObjectFunction( int _id, JSFunction* _function,
const int _deliveryTime, JSObject* _operateOn = NULL )
: SDispatchObject( _id, _deliveryTime ), function( _function ), operateOn( _operateOn ) {}
inline SDispatchObjectFunction( int _id, JSFunction* _function,
const int _deliveryTime, JSObject* _operateOn, const int recurrence )
: SDispatchObject( _id, _deliveryTime, recurrence ), function( _function ), operateOn( _operateOn ) {}
};
struct CScheduler : public Singleton<CScheduler>
{
std::priority_queue<SDispatchObjectScript> timeScript, frameScript;
std::priority_queue<SDispatchObjectFunction> timeFunction, frameFunction;
std::list<CJSProgressTimer*> progressTimers;
int m_nextTaskId;
bool m_abortInterval;
STL_HASH_SET<int> tasksToCancel;
CScheduler();
int PushTime( int delay, const CStrW& fragment, JSObject* operateOn = NULL );
int PushFrame( int delay, const CStrW& fragment, JSObject* operateOn = NULL );
int PushInterval( int first, int interval, const CStrW& fragment, JSObject* operateOn = NULL, int id = 0 );
int PushTime( int delay, JSFunction* function, JSObject* operateOn = NULL );
int PushFrame( int delay, JSFunction* function, JSObject* operateOn = NULL );
int PushInterval( int first, int interval, JSFunction* function, JSObject* operateOn = NULL, int id = 0 );
void PushProgressTimer( CJSProgressTimer* progressTimer );
void CancelTask( int id );
void Update(int elapsedSimulationTime);
};
#define g_Scheduler CScheduler::GetSingleton()
class CJSProgressTimer : public CJSObject<CJSProgressTimer>
{
friend struct CScheduler;
double m_Max, m_Current, m_Increment;
JSFunction* m_Callback;
JSObject* m_OperateOn;
CJSProgressTimer( double Max, double Increment, JSFunction* Callback, JSObject* OperateOn );
static JSBool Construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
public:
static void ScriptingInit();
};
extern const int ORDER_DELAY;
#endif

View File

@ -25,7 +25,6 @@
#include "ScriptGlue.h"
#include "JSConversions.h"
#include "Scheduler.h"
#include "ScriptableComplex.inl"
@ -112,169 +111,8 @@ JSBool WriteLog(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval)
// Timer
//-----------------------------------------------------------------------------
// Request a callback be executed after the specified delay.
// params: callback [fragment or function], delay in milliseconds [int]
// returns:
// notes:
// - Scripts and functions registered this way are called on the first
// simulation frame after the specified period has elapsed. If this causes
// multiple segments of code to be executed in the same frame,
// relative timing is maintained. Delays of 0 milliseconds cause code to be
// executed on the following simulation frame. If more than one script or
// function is scheduled to execute in the same millisecond, the order of
// execution is undefined. Code is scheduled in simulation time, and is
// therefore suspended while the game is paused or frozen. Granularity of
// timing is also limited to 1/(Simulation frame rate); currently 100ms.
// The called function or script executes in the same scope as the
// code that called SetTimeout (amongst other things, the
// 'this' reference is usually maintained)
JSBool SetTimeout( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAM_RANGE(2, 3);
int delay;
try
{
delay = ToPrimitive<int>( argv[1] );
}
catch( PSERROR_Scripting_ConversionFailed )
{
JS_ReportError( cx, "Invalid timer parameters" );
return( JS_TRUE );
}
JSObject* scope;
if( argc == 3 )
{
if( !JSVAL_IS_OBJECT( argv[2] ) )
{
JS_ReportError( cx, "Invalid timer parameters" );
return( JS_TRUE );
}
scope = JSVAL_TO_OBJECT( argv[2] );
}
else
{
scope = JS_GetScopeChain( cx );
}
switch( JS_TypeOfValue( cx, argv[0] ) )
{
case JSTYPE_STRING:
{
CStrW fragment = g_ScriptingHost.ValueToUCString( argv[0] );
int id = g_Scheduler.PushTime( delay, fragment, scope );
*rval = INT_TO_JSVAL( id );
return( JS_TRUE );
}
case JSTYPE_FUNCTION:
{
JSFunction* fn = JS_ValueToFunction( cx, argv[0] );
int id = g_Scheduler.PushTime( delay, fn, scope );
*rval = INT_TO_JSVAL( id );
return( JS_TRUE );
}
default:
JS_ReportError( cx, "Invalid timer script" );
return( JS_TRUE );
}
}
// Request a callback be executed periodically.
// params: callback [fragment or function], initial delay in ms [int], period in ms [int]
// OR callback [fragment or function], period in ms [int] (initial delay = period)
// returns:
// notes:
// - SetTimeout's notes apply here as well.
JSBool SetInterval( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAM_RANGE(2, 3);
int first, interval;
try
{
first = ToPrimitive<int>( argv[1] );
if( argc == 3 )
{
// toDo, first, interval
interval = ToPrimitive<int>( argv[2] );
}
else
{
// toDo, interval (first = interval)
interval = first;
}
}
catch( PSERROR_Scripting_ConversionFailed )
{
JS_ReportError( cx, "Invalid timer parameters" );
return( JS_TRUE );
}
switch( JS_TypeOfValue( cx, argv[0] ) )
{
case JSTYPE_STRING:
{
CStrW fragment = g_ScriptingHost.ValueToUCString( argv[0] );
int id = g_Scheduler.PushInterval( first, interval, fragment, JS_GetScopeChain( cx ) );
*rval = INT_TO_JSVAL( id );
return( JS_TRUE );
}
case JSTYPE_FUNCTION:
{
JSFunction* fn = JS_ValueToFunction( cx, argv[0] );
int id = g_Scheduler.PushInterval( first, interval, fn, JS_GetScopeChain( cx ) );
*rval = INT_TO_JSVAL( id );
return( JS_TRUE );
}
default:
JS_ReportError( cx, "Invalid timer script" );
return( JS_TRUE );
}
}
// Cause all periodic functions registered via SetInterval to
// no longer be called.
// params:
// returns:
// notes:
// - Execution continues until the end of the triggered function or
// script fragment, but is not triggered again.
JSBool CancelInterval( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_NO_PARAMS();
g_Scheduler.m_abortInterval = true;
return( JS_TRUE );
}
// Cause the scheduled task (timeout or interval) with the given ID to
// no longer be called.
// params:
// returns:
// notes:
// - Execution continues until the end of the triggered function or
// script fragment, but is not triggered again.
JSBool CancelTimer( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAMS(1);
try
{
int id = ToPrimitive<int>( argv[0] );
g_Scheduler.CancelTask( id );
}
catch( PSERROR_Scripting_ConversionFailed )
{
JS_ReportError( cx, "Invalid ID parameter" );
return( JS_TRUE );
}
return( JS_TRUE );
}
//Set the simulation rate scalar-time becomes time * SimRate.
//Params: rate [float] : sets SimRate
// Set the simulation rate scalar-time becomes time * SimRate.
// Params: rate [float] : sets SimRate
JSBool SetSimRate(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval)
{
JSU_REQUIRE_PARAMS(1);
@ -856,10 +694,6 @@ JSFunctionSpec ScriptFunctionTable[] =
JS_FUNC("toggleSky", ToggleSky, 0)
// Timer
JS_FUNC("setTimeout", SetTimeout, 2)
JS_FUNC("setInterval", SetInterval, 2)
JS_FUNC("cancelInterval", CancelInterval, 0)
JS_FUNC("cancelTimer", CancelTimer, 0)
JS_FUNC("setSimRate", SetSimRate, 1)
// Profiling

View File

@ -54,6 +54,8 @@ ScriptingHost::ScriptingHost()
if(!m_Context)
throw PSERROR_Scripting_SetupFailed();
// JS_SetGCZeal(m_Context, 2);
JS_SetErrorReporter(m_Context, ScriptingHost::ErrorReporter);
JS_BeginRequest(m_Context);