Journal codefool's Journal: Time-Sliced Procedures in Javascript
/////////////////////////////////////////////////////////////////////////////////////////
//
// clsTimeSlice
//
// The atomic time slice object. Represents either a function call or a method call
// to an object. The evoked function/method must answer false to continue processing, or
// true to terminate it.
//
function clsTimeSlice( fnSlice, objObj, name, latency )
{
this.fnSlice = fnSlice;
this.obj = objObj;
this.name = name;
this.latency = ( null == latency || latency < 1 ) ? clsTimeSlicedProc.SLICE_LATENCY : latency;
}
clsTimeSlice.prototype.exec =
function()
{
var bRet;
if( null != this.obj )
bRet = this.fnSlice.call( this.obj );
else
bRet = this.fnSlice();
return bRet;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// clsTimeSlicedProc
//
// Container for a time-sliced procedure.
//
function clsTimeSlicedProc( sObjectName )
{
this.init( sObjectName );
}
clsTimeSlicedProc.CHAIN_INDEX = -1;
clsTimeSlicedProc.SLICE_LATENCY = 2; // #ms between slices
clsTimeSlicedProc.prototype.init =
function( sObjectName )
{
this.name = sObjectName;
this.slices = new Array();
this.sliceChain = null;
this.latch = false;
this.next = 0;
this.error = 0;
this.run = false;
}
clsTimeSlicedProc.prototype.reset = function() { this.init( this.name ); }
clsTimeSlicedProc.prototype.sliceCnt = function() { return this.slices.length; }
clsTimeSlicedProc.prototype.slice =
function( idx )
{
if( idx < this.sliceCnt() )
return this.slices[ idx ];
return null;
}
clsTimeSlicedProc.prototype.latched = function() { return this.latch; };
clsTimeSlicedProc.prototype.addSlice = function( s ) { this.slices[ this.slices.length ] = s; return s; }
clsTimeSlicedProc.prototype.createSlice = function( f, o, n, l ) { this.addSlice( new clsTimeSlice( f, o, n, l ) ); return this; }
clsTimeSlicedProc.prototype.addFunction = function( f, n, l ) { this.addSlice( new clsTimeSlice( f, null, n, l ) )._f = true; return this; }
clsTimeSlicedProc.prototype.chain = function( f, o, n, l ) { this.sliceChain = new clsTimeSlice( f, o, n, l ); return this; }
clsTimeSlicedProc.prototype.setErrorCode = function( c ) { this.error = c; }
clsTimeSlicedProc.prototype.hasError = function() { return !!( this.error != 0 ); }
clsTimeSlicedProc.prototype.finish = function() { this.next = clsTimeSlicedProc.CHAIN_INDEX; }
clsTimeSlicedProc.prototype.begin =
function()
{
if( this.latch )
return false;
this.latch = true;
this._doSlice( this.next );
return true;
}
clsTimeSlicedProc.prototype.setNextSlice =
function( indexOrName )
{
if( typeof indexOrName == "string" )
{
// search for a slice by name
for( var idx = 0; idx < this.slices.length; idx++ )
{
if( this.slice( idx ).name == indexOrName )
{
this.next = idx;
break;
}
}
if( idx >= this.slices.length )
alert( this.name + ": Not able to find slice with tag '" + indexOrName + "'" );
}
// must allow index to exceed slice count in order for loop to ever terminate!
else if( indexOrName <= this.sliceCnt() )
this.next = indexOrName;
}
clsTimeSlicedProc.prototype._doSlice =
function( iIndex )
{
var l = ( iIndex in this.slices ) ? this.slices[ iIndex ].latency : clsTimeSlicedProc.SLICE_LATENCY;
setTimeout( this.name + ".exec( " + iIndex + ")", l );
}
clsTimeSlicedProc.prototype.exec =
function( iIndex )
{
if( clsTimeSlicedProc.CHAIN_INDEX == iIndex )
{
if( null != this.sliceChain )
this.sliceChain.exec();
this.sliceChain = null; // chain is a one-shot deal
this.latch = false;
}
else
{
if( !this.hasError() && iIndex < this.sliceCnt() )
{
this.setNextSlice( iIndex + 1 );
if( this.slices[ iIndex ].exec() || this.slices[ iIndex ]._f )
iIndex = this.next;
this._doSlice( iIndex );
}
else
{
this._doSlice( clsTimeSlicedProc.CHAIN_INDEX );
}
}
}
//
// clsTimeSlice
//
// The atomic time slice object. Represents either a function call or a method call
// to an object. The evoked function/method must answer false to continue processing, or
// true to terminate it.
//
function clsTimeSlice( fnSlice, objObj, name, latency )
{
this.fnSlice = fnSlice;
this.obj = objObj;
this.name = name;
this.latency = ( null == latency || latency < 1 ) ? clsTimeSlicedProc.SLICE_LATENCY : latency;
}
clsTimeSlice.prototype.exec =
function()
{
var bRet;
if( null != this.obj )
bRet = this.fnSlice.call( this.obj );
else
bRet = this.fnSlice();
return bRet;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// clsTimeSlicedProc
//
// Container for a time-sliced procedure.
//
function clsTimeSlicedProc( sObjectName )
{
this.init( sObjectName );
}
clsTimeSlicedProc.CHAIN_INDEX = -1;
clsTimeSlicedProc.SLICE_LATENCY = 2; // #ms between slices
clsTimeSlicedProc.prototype.init =
function( sObjectName )
{
this.name = sObjectName;
this.slices = new Array();
this.sliceChain = null;
this.latch = false;
this.next = 0;
this.error = 0;
this.run = false;
}
clsTimeSlicedProc.prototype.reset = function() { this.init( this.name ); }
clsTimeSlicedProc.prototype.sliceCnt = function() { return this.slices.length; }
clsTimeSlicedProc.prototype.slice =
function( idx )
{
if( idx < this.sliceCnt() )
return this.slices[ idx ];
return null;
}
clsTimeSlicedProc.prototype.latched = function() { return this.latch; };
clsTimeSlicedProc.prototype.addSlice = function( s ) { this.slices[ this.slices.length ] = s; return s; }
clsTimeSlicedProc.prototype.createSlice = function( f, o, n, l ) { this.addSlice( new clsTimeSlice( f, o, n, l ) ); return this; }
clsTimeSlicedProc.prototype.addFunction = function( f, n, l ) { this.addSlice( new clsTimeSlice( f, null, n, l ) )._f = true; return this; }
clsTimeSlicedProc.prototype.chain = function( f, o, n, l ) { this.sliceChain = new clsTimeSlice( f, o, n, l ); return this; }
clsTimeSlicedProc.prototype.setErrorCode = function( c ) { this.error = c; }
clsTimeSlicedProc.prototype.hasError = function() { return !!( this.error != 0 ); }
clsTimeSlicedProc.prototype.finish = function() { this.next = clsTimeSlicedProc.CHAIN_INDEX; }
clsTimeSlicedProc.prototype.begin =
function()
{
if( this.latch )
return false;
this.latch = true;
this._doSlice( this.next );
return true;
}
clsTimeSlicedProc.prototype.setNextSlice =
function( indexOrName )
{
if( typeof indexOrName == "string" )
{
for( var idx = 0; idx < this.slices.length; idx++ )
{
if( this.slice( idx ).name == indexOrName )
{
this.next = idx;
break;
}
}
if( idx >= this.slices.length )
alert( this.name + ": Not able to find slice with tag '" + indexOrName + "'" );
}
else if( indexOrName <= this.sliceCnt() )
this.next = indexOrName;
}
clsTimeSlicedProc.prototype._doSlice =
function( iIndex )
{
var l = ( iIndex in this.slices ) ? this.slices[ iIndex ].latency : clsTimeSlicedProc.SLICE_LATENCY;
setTimeout( this.name + ".exec( " + iIndex + ")", l );
}
clsTimeSlicedProc.prototype.exec =
function( iIndex )
{
if( clsTimeSlicedProc.CHAIN_INDEX == iIndex )
{
if( null != this.sliceChain )
this.sliceChain.exec();
this.sliceChain = null;
this.latch = false;
}
else
{
if( !this.hasError() && iIndex < this.sliceCnt() )
{
this.setNextSlice( iIndex + 1 );
if( this.slices[ iIndex ].exec() || this.slices[ iIndex ]._f )
iIndex = this.next;
this._doSlice( iIndex );
}
else
{
this._doSlice( clsTimeSlicedProc.CHAIN_INDEX );
}
}
}
Time-Sliced Procedures in Javascript More Login
Time-Sliced Procedures in Javascript
Slashdot Top Deals