contents   index   previous   next



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.


#define MAX_FIBERS 5



/* ---------------------------------------------------------

 * Error handler

 * --------------------------------------------------------- */


   SE_CALLBACK( void )

my_error_printer(secontext se,seconstcharptr text)


   printf_sechar(UNISTR("Error encountered: %s\n"),text);



/* 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

 * --------------------------------------------------------- */


   SE_CALLBACK( void )

StringOut(secontext se,sememcount argc)


   sememcount i;

   seconstcharptr text;


   for( i=0;i<argc;i++ )


      /* Get each successive argument and print them


      text = seGetString(se, SE_ARGS,SE_NUM(i), NULL);





SE_BEGIN_LIB_TABLE( SampleFunctionList )

   SE_FUNCTION( "StringOut",    StringOut,      1, -1,  

                SE_SECURE, SE_DONTENUM ),





add_fiber(secontext se,secontext *table,int *number,

          seobject glob)


   assert( (*number)<MAX_FIBERS );

   table[(*number)++] = se;


   /* give the fiber a private global */


   /* but point back to shared so can see it */



   seEval(se,UNISTR("var a = 10;\nStringOut(a);\n"),SE_TEXT,





remove_fiber(int num,secontext *table,int *number)


   assert( num<(*number) );


   /* we are done with the context */



   /* remove it from the table */

   while( num<(*number)-1 )


      table[num] = table[num+1];







main(int argc,char **argv)


   secontext se;

   secontext fibers[MAX_FIBERS];

   int fibers_used = 0;

   int fiber_current = 0;

   seobject shared_global;

   struct seContextParams params;







   /* the print error function is the one required function. */

   params.sePrintErrorFunc = my_error_printer;


   /* initialize the main context */

   se = seCreateContext(&params,MY_JSE_USER_KEY);

   if( se==NULL )


      printf_sechar(UNISTR("Invalid user key.\n"));




   shared_global = seGetObject(se,SE_GLOBAL,SE_VALUE);


   /* add libaries so we have the StringOut function */




   /* Add the original context to our fiber list. All contexts

    * including the parent will be treated identically





   /* Create some more fibers. All are added to one big

    * pool.


   while( fibers_used<MAX_FIBERS )





   /* 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 )


      if( !seExec(fibers[fiber_current]) )



         /* and continue using the fiber that fell into its

          * place







      if( fiber_current>=fibers_used ) fiber_current = 0;




   /* Done with the sample, shut everything down. */