Description
This is addressing the "Tasks" portion of #10493, and I'm opening this to become a clear action item.
If the task::spawn
function is invoked, and there is no local Scheduler
available (basically in_green_task_context()
return false), then we should fall back to using a kernel thread to perform the spawn. The semantics, however, should remain the same. What this means is that the following steps need to happen:
- A new kernel thread is started, probably via
rt::thread::Thread
. - This thread allocates
~Task
and moves it into the appropriate thread-local-storage slot - Invoke the equivalent of
rt::task::Task.run
. This will set up the C++ try/catch block, as well as cleaning up unconditionally after the task runs. (things like deallocating task-local storage, cleaning up GC, clearing out the stdout/logger handles, etc). - Run the input closure.
In addition, to these steps, the current semantics of task::spawn
is that nothing is immediately returned, meaning that just using Thread::start
will not work (because it returns a handle). I believe this will involve adding a detach
function to the Thread
struct which would do something along the lines of pthread_detach
on unix and CloseHandle
on windows.
With this in place, I should be able to invoke task::spawn
with and without the runtime. It is OK to require that a one-time runtime initialization function is run before any of this spawning code to run, but it is not OK for this one-time initialization function to require all future code to be run in a closure (i.e. what happens today).
Hence, a program like this should run successfully:
fn start(argc: int, argv: **u8) -> int {
rt::init(argc, argv); // may optional, maybe not, depends on implementation
do spawn {
println!("hello from a new rust task running on a different thread!");
}
3
}