Googles appar
Huvudmeny

Post a Comment On: cbloom rants

"02-23-13 - Threading - Reasoning Behind Coroutine Centric Design"

7 Comments -

1 – 7 of 7
Blogger Fabian Giesen said...

Again, you might want to check out the Go (www.golang.org) runtime.

They always try to maintain a given number of active worker threads that run "goroutines".

If one of them starts a syscall - any syscall - it might end up waiting or blocking internally. In their syscall wrapper, they just mark the active thread as inside a syscall, which means it ceases being a normal worker, so your active worker count is down. The runtime may then later spawn another worker thread to bring the worker count up to what it should be (whether it actually does depends on how long the syscall takes).

After the syscall is done, you might now have an extra thread. In that case, the syscall thread goes to sleep; it might get swapped back in later to pick up work as another thread enters a syscall.

It's a really nice way for a worker-thread-centric environment to interface with OS primitives and libraries that aren't, with minimal friction.

February 25, 2013 at 1:16 PM

Blogger won3d said...

In other links Charles won't look at:

http://swtch.com/libtask/

...which was done by own of the main Go developers prior to his working on Go. Single-threaded, but the interface is basically the right one.

Go, naturally, does a better job of it.

February 26, 2013 at 12:55 PM

Blogger cbloom said...

WTF.

February 26, 2013 at 1:28 PM

Blogger jfb said...

Charles, have you tried prototyping it with Mono Continuations (http://www.mono-project.com/Continuations)?

Mono's garbage collected, embeddable, and with this primitive what you speak of can be built.

February 28, 2013 at 9:21 AM

Blogger cbloom said...

jfb, the easiest prototype would just be on Windows Fibers, which basically does everything I need (including turning OS waits into yields for me). Combine that with the Oodle "future" system of automatic dependencies and it's the system I propose.

The problem is I can't actually use it, because in my current situation I don't get to do architecture. The client sets the architecture and I have to work in it.

One difficulty with coroutine-centric-design is that it doesn't work great half way.

Like if the client has a few normal threads, and I have coroutine workers, and they are calling me from normal threads, you have put something in the TLS to say "is this a client thread or one of mine" and then everything you do has to check that bool and behave differently. It's a mess and very easy to make deadlocks and other problems.

I'm convinced that the full system is the way to go, and I would try doing a game that way. (I would also use the lock-free weak-reference object table with a builtin RWlock).

March 1, 2013 at 9:53 AM

Blogger Stephan said...

Do you have an opinion on whether its better to move the blocking system call to a new thread (e.g. in an IO thread pool) or instead activate a new worker thread for executing coroutines and do the system call on the current thread?

Can you think of realistic situations where a fixed cap on the number of threads (say, 2 * #processor) in blocking system calls (excluding network IO) could lead to a deadlock?

March 5, 2013 at 1:08 PM

Blogger cbloom said...

I don't see a problem off hand.

You have to ensure that nothing in your system ever does an OS Wait() on other jobs, only Yield. That ensures forward progress. Also obviously you have to ensure no circles in the dependency graph. Also if any jobs poll for completion rather than doing a proper yield, that can lead to livelocks and priority inversions.

March 5, 2013 at 1:33 PM

You can use some HTML tags, such as <b>, <i>, <a>

This blog does not allow anonymous comments.

Comment moderation has been enabled. All comments must be approved by the blog author.

You will be asked to sign in after submitting your comment.