Tom Locke wrote:
> 
> OK, here's what I'm hoping Parrot can provide for the language I'm building.
> 
> My big requirement is for lightweight microthreads (hopefully *very*
> lightweight - I'm considering one scheduler that can handle *millions*
> of threads on a single machine).

Hmm, I can envision a microthread implementation wherein each
microthread is nothing more than a Continuation PMC.

Add an interpreter->microthreads PMC* pointer.  (This could be a global
stored in interpreter->perl_stash->stash_hash, but that wouldn't be as
fast).  Then, add the following ops:

   inline op init_microthreads() {
      if( !interpreter->microthreads )
         interpreter->microthreads =
            new_pmc(interpreter, enum_class_PerlArray);
      goto NEXT();
   }

=item B<mthread_create>(in PMC)
Create a new microthread, which will start with the Continuation in $1.
=cut

   inline op mthread_create(in PMC) {
      VTABLE_push(interpreter, interpreter->microthreads, $1);
      goto NEXT();
   }

=item B<mthread_create>(inconst INT)
Create a new Continuation, with the address set to $1, and 
=cut

   inline op mthread_create(inconst INT) {
      opcode_t *dest = PTR2OPCODE_T(CUR_OPCODE + $1));
      PMC * p = new_ret_continuation_pmc(interpreter, dest)
      VTABLE_push(interpreter, interpreter->microthreads, p);
      goto NEXT();
   }

=item B<mthread_yieldcc>()
Create a new Continuation (which resumes after this op), schedule
it to activate later, and then switch to the next microthread.
=cut

   inline op mthread_yieldcc() {
      opcode_t *dest = expr NEXT();
      PMC * p = new_ret_continuation_pmc(interpreter, dest);
      VTABLE_push(interpreter, interpreter->microthreads, $1);
      p = VTABLE_shift(interpreter, interpreter->microthreads);
      dest = (opcode_t *)VTABLE_invoke(interpreter, p, dest);
      goto ADDRESS(dest); 
   }

=item B<mthread_yield>(in PMC)
Schedule the Continuation in $1, then switch to the next microthread.
=cut

   inline op mthread_yield(in PMC) {
      opcode_t *dest = expr NEXT();
      PMC * p;
      VTABLE_push(interpreter, interpreter->microthreads, $1);
      p = VTABLE_shift(interpreter, interpreter->microthreads);
      dest = (opcode_t *)VTABLE_invoke(interpreter, p, dest);
      goto ADDRESS(dest); 
   }

=item B<mthread_yield>(inconst INT)
Create a new Continuation, which resumes at address $1, then switch
to the next microthread.
=cut

   inline op mthread_yield(inconst INT) {
      opcode_t *dest = PTR2OPCODE_T(CUR_OPCODE + $1);
      PMC * p = new_ret_continuation_pmc(interpreter, dest);
      VTABLE_push(interpreter, interpreter->microthreads, p);
      p = VTABLE_shift(interpreter, interpreter->microthreads);
      dest = (opcode_t *)VTABLE_invoke(interpreter, p, dest);
      goto ADDRESS(dest); 
   }

   inline op mthread_fork() {
      PMC * p = new_ret_continuation_pmc(interpreter, expr NEXT());
      VTABLE_push(interpreter, interpreter->microthreads, p);
      goto NEXT() 
   }

> Oh and I will need them to be serializable.

I hope you aren't planning on serializing just a single isolated
microthread... that wouldn't work well with what I've got in mind due to
how much stuff comes along when you serialize a continuation -- you'd
get almost the whole interpreter serialized.

If you want, instead, to serialize interpreter->microthreads, however...
well, you'd *still* get almost the whole interpreter serialized, but
you're getting more bang for your buck :)

> I can live with co-operative scheduling, perhaps running
> 'regular' threads over the top do provide a layer of preemptive
> scheduling.

Remember, each thread has it's own interpreter.  This means that one
would have to share ->microthreads amongst multiple interpreters. 
Besides the very minor nuisance of locking for ->push and ->shift,
there's the very big headach of figuring out what happens when you
invoke a continuation created in one interpreter in another interpreter.

An easier solution might be to create a timer event which, when handled,
does a yieldcc.

[PS: All code in this message is UNTESTED.  If you'd *like* to test, be
my guest! :)]

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}

Reply via email to