GLOBAL MANIPULATION
Although the intent of fibers is to conserve memory by sharing overhead, often each fiber should still be independent. For instance, you may not want them to share global variables. This is easy to accomplish. After you create the initial context and set up the libraries in it using seCreateContext, you preserve that global object. Then for each fiber (including the original context returned by seCreateContext), you give it a new global object with its _prototype pointing to the preserved global object. Thus, all new variables created in a fiber will be created in its private global object, yet it still can refer via the global’s prototype to the original global object which contains all the standard function libraries.
Here is a short example ScriptEase API application that creates several fibers and runs them all.
public class FibersSample implements
SEContextParams, SEErrorHandler, SELibrary
{
static final int MAX_FIBERS = 5;
private int seOptions;
/* ---------------------------------------------------------
* SEContextParams interface
* ---------------------------------------------------------*/
public int seGetOptions()
{
return this.seOptions;
}
public void seSetOptions(int options)
{
this.seOptions = options;
}
/* ---------------------------------------------------------
* Error handler
* ---------------------------------------------------------*/
public void sePrintErrorFunc(SEContext se, String text)
{
System.out.println("Error encountered: " + text);
}
/* ---------------------------------------------------------
* SELibrary interface
* ---------------------------------------------------------*/
public SELibrary seLibraryInitFunc(SEContext se)
{
return this;
}
public void seLibraryTermFunc(SEContext se)
{
}
/* A wrapper function to write out a string. It converts
* whatever argument it is given to a string then writes it
* to the terminal using 'printf'. The user would use it like
* this:
*
* StringOut("Hello, world!");
*/
/* ---------------------------------------------------------
* Text output
* ---------------------------------------------------------*/
public SEWrapper StringOut()
{
return new SEWrapper()
{
public void wrapperFunction(SEContext se, int argc)
{
int i;
String text;
for( i=0;i<argc;i++ )
{
/* Get each successive argument and print them
*/
text = se.seGetString(SE.ARGS,SE.NUM(i));
System.out.println(text);
}
}
};
}
SELibraryTableEntry[] SampleFunctionList =
{
SE.FUNCTION( "StringOut", StringOut(), 1, -1,
SE.SECURE, SE.DONTENUM )
};
static void add_fiber(SEContext se,
SEContext[] table,
int[] number,
SEObject glob)
{
table[(number[0])++] = se;
/* give the fiber a private global */
se.sePutObject(SE.GLOBAL,SE.VALUE,se.seMakeObject());
/* but point back to shared so can see it */
se.sePutObject(SE.GLOBAL,
SE.STOCK(JseStrID._prototype),
glob);
se.seEval("var a = 10;\nStringOut(a);\n",SE.TEXT,
null,null,SE.START,null);
}
static void remove_fiber(int num,
SEContext[] table,
int[] number)
{
/* we are done with the context */
table[num].seDestroyContext();
/* remove it from the table */
while( num<(number[0])-1 )
{
table[num] = table[num+1];
num++;
}
(number[0])--;
}
public static final void main(String[] argv)
{
SEContext se;
SEContext[] fibers = new SEContext[MAX_FIBERS];
int[] fibers_used = {0};
int fiber_current = 0;
SEObject shared_global;
FibersSample sample = new FibersSample();
sample.seSetOptions(SE.DEFAULT);
SE.seInitialize();
/* initialize the main context */
se = SE.seCreateContext(sample,null);
if( se==null )
{
System.err.println("Invalid user key.");
System.exit(0);
}
shared_global = se.seGetObject(SE.GLOBAL,SE.VALUE);
/* add libaries so we have the StringOut function */
se.seAddLibTable(sample.SampleFunctionList,sample);
/* Add the original context to our fiber list. All contexts
* including the parent will be treated identically
*/
add_fiber(se,fibers,fibers_used,shared_global);
/* Create some more fibers. All are added to one big
* pool.
*/
while( fibers_used[0]<MAX_FIBERS )
add_fiber(fibers[0].seCreateFiber(),fibers,
fibers_used,shared_global);
/* run the fibers until all have exited. For each fiber,
* execute its next available statement using seExec().
* Notice that an seEval using SE.START was started in
* each fiber when it was added above. As each fiber
* finishes its seEval(), we remove it from the fiber list.
* We exit when all fibers are done.
*/
while( fibers_used[0]>0 )
{
if( !fibers[fiber_current].seExec() )
{
remove_fiber(fiber_current,fibers,fibers_used);
/* and continue using the fiber that fell into its
* place
*/
}
else
{
fiber_current++;
}
if( fiber_current>=fibers_used[0] ) fiber_current = 0;
}
/* Done with the sample, shut everything down. */
SE.seTerminate();
}
}