Ahoyhoy,
Glad to see you all again in 2004, and what a lovely swag of christmas
patches to find under our tree :-)
I've checked in basic support for Emacs to have multiple connections
to Lisps simultaneously. Today this means you can connect to several
Lisps at the same time, and even concurrently debug different programs
like Peter described. For the future the plan is to try Gary Byers's
idea of using this as the basis of multithreading support.
The current user-interface is very minimal, only really usable for
testing. `M-x slime-connect' now gives you the option of keeping your
existing connections alive. If you have multiple connections, you can
cycle your "primary" connection (used for REPL, C-c :, and so on) with
`M-x slime-next-connection'. Various buffers, e.g. the debugger,
apropos results, etc, are "sticky" -- they will always use the
connection that they were created by.
Methinks the next step is to allow multiple REPLs and have `M-x slime'
support multiple *inferior-lisp*s.
For now it's best to wait before trying this out as a user. The
purpose of this mail is really to describe what I've done to the code,
not to advertise features that actually work well :-)
So - down to the code:
Previously we had just one "process" (socket), used for everything:
(defvar slime-net-process nil
"The process (socket) connected to the CL.")
But now we have many processes, one of which is in use at a time:
(defvar slime-net-processes nil
"List of processes (sockets) connected to Lisps.")
and
(defvar slime-connection nil
"Network process currently in use.")
`slime-net-processes' is for the low-level networking code to know
what connections we have so that we can poll them for input and so on.
`slime-connection' is the process that we should actually use to send
commands to Lisp.
We also recorded information about Lisp in global variables, like:
(defvar slime-pid nil
"The process id of the Lisp process.")
But globals don't cut it with multiple Lisps, so now these become
"connection-local variables". These variables are only used via
accessor functions, and are really kept as buffer-local variables
inside the process-buffer of each connection. For example:
(slime-def-connection-var slime-pid nil
"The process id of the Lisp process.")
Then we can say (slime-pid) to get the value for the current
connection (looked up in the process-buffer of `slime-connection' -
the currently active connection), and use (setf (slime-pid) ...) to
write it.
The cute part: because all connection-specific state is in
connection-local variables looked up indirectly, to "context-switch"
between connections we only have to rebind `slime-connection'. This
also means you can make a particular connection "sticky" for commands
in a given buffer just by making a buffer-local binding of
`slime-connection'. This is done in e.g. SLDB buffers to debug the
right Lisp.
My current plan is something like:
More usable UI.
Another round of backend refactoring, to pave the way for -
Automatic connection-per-thread multiprocessing support.
Other notes/confessions:
Each connection has a separate SLDB buffer.
All connections share a REPL, but this is possibly wrong and
definitely not working right.
Cheers,
Luke