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