Files
squirrel/doc/source/reference/language/threads.rst

107 lines
3.4 KiB
ReStructuredText
Raw Normal View History

2016-03-14 23:35:04 +08:00
.. _threads:
========================
Threads
========================
.. index::
single: Threads
Squirrel supports cooperative threads(also known as coroutines).
A cooperative thread is a subroutine that can suspended in mid-execution and provide a value to the
caller without returning program flow, then its execution can be resumed later from the same
point where it was suspended.
At first look a Squirrel thread can be confused with a generator, in fact their behaviour is quite similar.
However while a generator runs in the caller stack and can suspend only the local routine stack a thread
has its own execution stack, global table and error handler; This allows a thread to suspend nested calls and
have it's own error policies.
------------------
Using threads
------------------
.. index::
single: Using Threads
2016-03-14 23:35:04 +08:00
Threads are created through the built-in function 'newthread(func)'; this function
gets as parameter a squirrel function and bind it to the new thread objects (will be the thread body).
2016-03-14 23:35:04 +08:00
The returned thread object is initially in 'idle' state. the thread can be started with the function
'threadobj.call()'; the parameters passed to 'call' are passed to the thread function.
A thread can be be suspended calling the function suspend(), when this happens the function
that wokeup(or started) the thread returns (If a parameter is passed to suspend() it will
2016-03-14 23:35:04 +08:00
be the return value of the wakeup function , if no parameter is passed the return value will be null).
A suspended thread can be resumed calling the function 'threadobj.wakeup', when this happens
2016-03-14 23:35:04 +08:00
the function that suspended the thread will return(if a parameter is passed to wakeup it will
be the return value of the suspend function, if no parameter is passed the return value will be null).
A thread terminates when its main function returns or when an unhandled exception occurs during its execution.::
function coroutine_test(a,b)
{
::print(a+" "+b+"\n");
local ret = ::suspend("suspend 1");
::print("the coroutine says "+ret+"\n");
ret = ::suspend("suspend 2");
::print("the coroutine says "+ret+"\n");
ret = ::suspend("suspend 3");
::print("the coroutine says "+ret+"\n");
return "I'm done"
}
local coro = ::newthread(coroutine_test);
local susparam = coro.call("test","coroutine"); //starts the coroutine
local i = 1;
do
{
::print("suspend passed ("+susparam+")\n")
susparam = coro.wakeup("ciao "+i);
++i;
}while(coro.getstatus()=="suspended")
::print("return passed ("+susparam+")\n")
the result of this program will be::
test coroutine
suspend passed (suspend 1)
the coroutine says ciao 1
suspend passed (suspend 2)
the coroutine says ciao 2
suspend passed (suspend 3)
the coroutine says ciao 3
return passed (I'm done).
the following is an interesting example of how threads and tail recursion
can be combined.::
function state1()
{
::suspend("state1");
return state2(); //tail call
}
function state2()
{
::suspend("state2");
return state3(); //tail call
}
function state3()
{
::suspend("state3");
return state1(); //tail call
}
local statethread = ::newthread(state1)
::print(statethread.call()+"\n");
for(local i = 0; i < 10000; i++)
::print(statethread.wakeup()+"\n");