Green Threads: The Task API

Now that I have pre-emptive task switching between green threads basically working, I need to figure out what the API to interact with them wants to look like. Additionally, I need to clean up this scheduler thing that I've mauled in order to make the API and terminology consistent.

I'm going to call a green thread a Task (what Parrot used to call a Task is now called an Event - Task was too good a word for this apparently unused feature). I plan to implement the following Task API:

Everyone can:

  • Create a task (new 'Task'; schedule opcode)
  • List all tasks (new 'Scheduler'; active_tasks method)

Anyone with a task handle can:

  • Send it a message (Task#send)
  • Wait for it to finish (wait opcode)
  • Kill it (Task#kill)

The active task can:

  • Exit (end opcode)
  • Yield the rest of its quantum to the next task in the queue (pass opcode)
  • Receive a message (receive opcode)

Events probably won't be cleaned up and made to work, but if they were it would look something like this:

Everyone can:

  • Register an EventHandler
  • Send an Event for handling

When an event gets shipped, it's matched to an appropriate handler and that combination gets scheduled as a Task.

kill vs. interrupt

Java took an interesting approach to killing threads. Instead of just stopping a thread in its tracks, you do one of two things: 1) if it's busy, you set a flag marking the thread as interrupted which it must check at the next convenient opportunity; 2) if it's waiting for something (IO, sleep, lock) then the interrupted thread throws an InterruptedException.

This approach lets the interrupted thread finish gracefully every time, which I think is profoundly better than a non-negotiable kill. But it also requires the programmer to write some complicated behavior in *every* thread if you want to get this right.

That's neat

That is an useful way of doing it. I'm not sure how to interrupt IO ops without killing the OS thread, especially on Windows, but if Java is doing it then it must be possible. I'll have to look into it - having a "raise exception in target thread, right now, no matter what it's doing" capability would definitely be useful.

kill vs. interrupt

That's even pretty much the only way of doing it that will work in the end wrt resource cleanup. I think I've only seen a single thread API where kill hasn't been deprecated.

In contrast to what chrisdolan said, I don't think it's much of a burden for the application programmers. In Java, for instance, you only run into problems if you catch Throwable and don't re-throw the InterruptedException.

As for the implementation, in Windows, you can use I/O cancellation to interrupt a thread that is blocked on I/O. http://msdn.microsoft.com/en-us/library/aa480216.aspx has a nice introduction. In Unix, you can of course just signal the thread, and the syscall should return EINTR.

Please do this the Right Way from the start, and skip Task#kill entirely.