Post by Guy Hulbert Post by Rich Collins
You get one interpreter per thread. Each interpreter contains
separate coroutines (and state). AFAIK, the only way ATM to
communicate between the interpreters is to use sockets.
Thanks. That seems consistent with what I've been hearing. My problem
is that I don't understand exactly what "interpreter", "VM", and
"thread" mean. The documentation (see below) indicates that some of
these terms may not be a very precise way to talk about Io.
It seems to me that most people (myself included) tend to use
"interpreter" and "VM" interchangeably, even if this isn't exactly
correct. A VM and an interpreter can exist independently (Ruby has no
VM, LLVM has no interpreter), but most interpreted languages tie them
together closely enough that the distinction isn't important from the
outside. I'd say that the interpreter is what is responsible for
converting the textual representation of your source into something that
can be run on the VM. The VM is what actually runs the program and
handles things like memory management and interfacing with the OS.
Some people consider a VM to represent some sort of abstract CPU (like
the JVM or LLVM), but I don't think that's absolutely required (or maybe
it is, but that doesn't mean a CPU must be something with registers and
memory buses and pipelines, either).
"Thread" typically means "OS thread", that is, a light-weight (sort of),
preemptible process that shares memory with other threads within the
same process. Less frequently, "thread" is used to describe a
coroutine, which is a non-preemptible form of lightweight process that
runs within a single OS thread. OS threads will use multiple CPUs but
a coroutine will not (as it resides within a single OS thread). Also,
OS threads are managed (as the name implies) by the operating system
whereas coroutines are managed by the language (the VM).
Post by Guy Hulbert Post by Rich Collins Post by Steve Dekorte
Btw, IoVM's can only have one OS thread in them at a time so using a
VM per thread/process is the only way to get multi-core concurrency
for executing Io code.
Is this constraint (a VM per OS thread) fixed ?
The answer to this (below) appears to be "no", since the documentation
says "should" rather than "can't". Steve's recent comment is presumably
more authoritative than the documentation but there seems to be some
Post by Rich Collins
I'm really confused now. I shall look at the documentation (and code).
Here is the relevent section of the documentation.
An IoState can be thought of as an instance of an Io "virtual
machine", although "virtual machine" is a less appropriate term
because it implies a particular type of implementation.
Io is multi-state, meaning that it is designed to support
multiple state instances within the same process. These
instances are isolated and share no memory so they can be safely
accessed simultaneously by different os threads, though a given
state should only be accessed by one os thread at a time.
I still don't understand "os threads". I understand threads to be
mini-processes but being entirely contained within one program so I
don't understand what a "state" being "accessed" by one os thread means.
OS threads share memory (within the same process anyway). This means
that any "state" (data structures, etc) that live within this shared
process can be read or written by any thread. The danger here is
two-fold: without sufficient locking, state can get confused by
simultaneous reads and writes by competing threads. With too much
locking, access to the state becomes serialized and your threaded
application performs no better than a single-threaded application (or
worse, can deadlock).
The easiest description of all the above would be:
OS process -> OS thread(s) -> coroutine(s)
where "->" can be read as "contains". Threads and coroutines naturally
share memory, processes do not (at least, not without external help from
the operating system).
Io complicates this picture slightly in that it uses OS threads, but
each thread is tied to a particular VM (IoState) and so they don't
*appear* to be able to access each other's data (from the Io side), even
though they exist within the same OS process and so *could* see each
others data (although probably not safely). I'll also note that I'm
speculating here quite a bit as I've not actually read most of the Io
source (nor would I expect to be much more enlightened if I did ;-)
Post by Guy Hulbert
This section of the documentation is under Embedding and discusses the C
implementation while my "understanding" above is from the Io side. A
diagram may help ... even if I have to read the code and draw it
It's worth noting at this point that while it sounds like threads are a
huge advantage (preemptive, can run on multiple CPU's, etc), in practice
they have many disadvantages compared to coroutines. They are
difficult to use properly and can use much more memory. Also, heavy use
of threads can cause the CPU to be poorly utilized as they can
invalidate the CPU cache and cause pipelines to be flushed, among other
things, so the CPU ends up doing more housekeeping and less processing
of your application.
My personal belief is that a hybrid approach is best, with threads being
used for managing multiple async/coroutine-based processes.
Anyway, I hope the above wasn't badly misleading or full of outright
misinformation, but YMMV.