------art_302377_29826324.1148728466260
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Regarding Solaris: its implementation of threads was what supplied the API
model for Posix threads, so you could say it's as close to the original sin
as anything. Most of the important Unix-like systems support the Posix model
more or less well, but (apart from major defects in some of the
implementations), the key nonportabilities relate to the scheduling
discipline. And the world seems to have arrived at a consensus that the
"typical" scheduling discipline for threads is pre-emptive, so these
differences are no longer that important.

Ironically, the Linux implementation of threads is closest to the one in
Windows, although the APIs couldn't be more different. (Win32 had
kernel-scheduled threads from the earliest beta releases in 1992, at least
three years before the Posix API was standardized.) In both Linux and
Windows, threads are "lightweight processes," relatively heavyweight
entities which are scheduled by the kernel. Ruby's threads (and the threads
in the early Java implementations) are pure userland threads, scheduled by a
library inside your process. (Solaris uses an extremely complex hybrid model
which in my opinion has proven to be far more trouble than it's worth.)

The reason that Ruby's threads are tightly intertwined with the interpreter
logic is because Ruby must prevent the possibility that one of your threads
may make a system call that will block in the kernel (like reading a disk
file or a network socket, accessing the system time, etc) and thus block
every thread in your program. Ruby uses the I/O multiplexer (select) to keep
this from happening.

Threads can be used for two basic purposes: to make your programs run
faster, or to make them easier to write. Ruby's (and Java's) threads seem
designed primarily to facilitate the latter. You can easily imagine several
kinds of problems that are easier to model if you have access to relatively
independent flows of control. Thus both languages have the "synchronize"
method, taking an arbitrary code block, which makes it easy to lock
relatively large chunks of code in "critical sections" without having to
really design proper synchronization sets.

But to effectively use threads for higher performance and concurrency
requires a large amount of experience and understanding, much of which takes
platform dependencies into account. For just one example, I would want to
use a spin lock in some situations, if I'm running on a multi-processor
machine on certain hardware platforms. Ruby doesn't have one.

It seems to me that Ruby's green-thread implementation is perfectly adequate
for most programmers' requirements. What I think might be interesting is an
extension that would provide access to native threads and synchronization
primitives in parallel with Ruby's (an early version of the EventMachine
library did this). Then you could write extensions that were far more
thread-hot than is possible with Ruby threads. It may be possible to do this
without disturbing the existing implementation. If you wanted to mix Ruby
threads with native threads, you'd just have to be careful to use the native
mutex rather than Ruby's in your Ruby threads.

------art_302377_29826324.1148728466260--