Since I don't think the three-tiered threading system is going to be
implemented very soon, I'd like to propose that thread creation
instead be done with one new method of a ParrotThread object:
=item C<thread_id = thread_object.'thread'(flags, subroutine, arguments...)>
Spawn a new thread. C<flags> is or'd together constants available from
C<runtime/parrot/include/thread.pasm>. Now, only one constant is defined:
=over 4
=item PARROT_THREAD_CLONE
Specifies that the created thread shall call clone_interpreter() to
'clone' state from the parent thread into the child thread.
=cut
C<subroutine> is the subroutine to run in the new thread. The
remaining arguments (any number is premitted) will be used as
arguments to the subroutine. The arguments shall be cloned into the
new interpreter unless they are shared PMCs.
After this method returns, the ParrotThread PMC shall become Undef.
[Rationale: ParrotThread inherits from ParrotInterpreter -- sensibly
-- but manipulating the interpreter in a seperate thread is dangerous,
especially since the interpreter shall be destroyed when the other
thread is joined or exits after it is 'detached'. An obvious
alternative is to morph the ParrotThread PMC into the thread ID which
I think would be unexpectedly magical. The use of thread IDs instead
of some 'thread handle' PMC represents no change from the original
implementation. If we do create a core running-thread PMC type, it
will probably end up just wrapping a thread ID and so its only
advantage is likely to be the syntax with which thread-manipulating
methods are called.]
The returned thread ID may be used with various methods on the
ParrotInterpreter object obtained by the getinterp opcode to
manipulate the running thread.
=cut
Comments welcome.
-- Charles Reiss
However, I'm not too sure whether this is the best answer. Maybe it would
be better to create a thread object for a thread that you intend to spawn,
just as you instantiate any other PMC, perhaps with some flags and the sub
being given as arguments to the constructor. Then perhaps use the invoke
v-table methods, invoking it like a sub, to actually spawn the new thread.
This way the thread object is around to call methods on to get its status,
change its priority etc. I guess invoking an already started thread again
would be an exception...
Jonathan
I'd prefer 'run' myself.
> However, I'm not too sure whether this is the best answer. Maybe it would
> be better to create a thread object for a thread that you intend to spawn,
> just as you instantiate any other PMC, perhaps with some flags and the sub
> being given as arguments to the constructor. Then perhaps use the invoke
> v-table methods, invoking it like a sub, to actually spawn the new thread.
> This way the thread object is around to call methods on to get its status,
> change its priority etc.
This would probably be a nice interface to provide for the common case. There
is a question of how it will interact with thread destruction: either
we will need
a way to keep information about a thread around well after it is destroyed
(even if as little as enough to reserve its thread ID) until we can be sure that
references to its wrapper objects are gone or we will need to specify
that rather
unexpected behavior can happen when attempts are made to use the thread
wrapper after the underlying thread has been detached or joined in another
thread (this unexpected behavior including the operations affecting an unrelated
thread).
The latter behavior is certainly the easier to implement, but if we did, I'd be
concerned about users not noticing the caveat, which is one reason why I
was reluctant to propose not using numerical thread ids (which should at
least suggest to users that they may be reused or become invalid). The
greater intuitiveness is probably worth it, however.
[snip]
-- Charles