From: Nikodemus S. <nik...@ra...> - 2006-09-15 13:07:03
|
What follows is my current (mostly implemented) plan for doing away with sessions. Before putting in the finishing touches I wanted to check if this rubs anyone the wrong way. I'd really like to remove sessions entirely and put this in before 1.0. Interface inspired by the OpenMCL take on this, but extended to be, well, extensible. Why: 1. Sessions are modeled after unix process handling in terminal, but threads are not shell spawned processes, even though they sometimes may act like them. Instead of mediating foreground / background threads we really want to mediate access to the user, but there may be several conceptual users, and if we can open multiple listeners, then there is no reason why multiple threads cannot talk to the same user simultaneously. 2. Sessions rely heavily on INTERRUPT-THREAD, including asynch uwinding, which is fundamentally bad. (See earlier discussions on asynch unwinds.) What: Terminal is an abstraction based on an exlusive access to an interactive two way stream: a terminal is owned by the thread that currently has exclusive access to it. By default SBCL is assumed to be running in a text-based terminal, in which case obtaining a terminal simply refers to gaining access to that sole terminal. This behaviour can however be customized, so that a thread that requires interaction with the user can have, for example, a new terminal window opened for it for as long as it needs it. (All symbols in package SB-EXT or SB-THREAD -- probably SB-THREAD.) In SBCL itself this interface is used to obtain an interactive stream for the debugger, etc. class TERMINAL Base class of all terminal objects. Can be subclassed. Initialization arguments: :IO Required. A two way stream used by the terminal. Accessible via the reader function TERMINAL-IO. :NAME Optional. An object used to name the terminal. Accesible via the reader function TERMINAL-NAME. A new terminal is initially unowned by any thread. variable *TERMINAL* Global special variable bound to the current terminal. Initially bound to an instance of TERMINAL whose TERMINAL-IO is *TERMINAL-IO*. function TERMINAL-IO &optional terminal => two-way-stream Returns the two way stream for the TERMINAL. The terminal defaults to *TERMINAL*. function TERMINAL-OWNER &optional terminal => thread Returns the thread that currently owns TERMINAL, or NIL if the terminal is unowned by any thread. The terminal defaults to *TERMINAL*. There is no guarantee that the thread is still alive or has access to the terminal by the time the function returns. function TERMINAL-NAME &optional terminal => object Returns the name of the TERMINAL. The terminal defaults to *TERMINAL*. generic function ACTIVATE-TERMINAL terminal Called after a thread is made the owner of the terminal. May be extended, but not overridden for subclasses of TERMINAL. generic function DEACTIVATE-TERMINAL terminal Called after a thread has released a terminal. May be extended, but not overridden for subclasses of TERMINAL. function GET-TERMINAL &optional terminal => terminal Waits until TERMINAL is available, makes the current thread its owner, calls ACTIVATE-TERMINAL with the terminal, and finally returns the terminal. The terminal defaults to *TERMINAL*. Has no effect aside from returning the terminal if the current thread is already the owner of the terminal. generic function RELEASE-TERMINAL &optional terminal => terminal Calls DEACTIVATE-TERMINAL with the TERMINAL, then makes the terminal unowned by the current thread, making it available for threads using GET-TERMINAL, and finally returns the terminal. The terminal defaults to *TERMINAL*. An error is signalled if the current thread is not the owner of the terminal. variable *FIND-TERMINAL-HOOK* Global special variable. Must be NIL, or a designator for a function callable with no arguments, used to find an interactive terminal. Defaults to NIL. See FIND-TERMINAL for details. function FIND-TERMINAL => terminal Attempts to find an interactive terminal. If *FIND-TERMINAL-HOOK* is not NIL, it should be a function designator. The designated function is called with no arguments and *FIND-TERMINAL-HOOK* bound to NIL. If *FIND-TERMINAL-HOOK* is NIL, or the function returns with a value that is not a terminal, *TERMINAL* is returned. macro WITH-TERMINAL (terminal) &body forms => value* Waits to get become owner of TERMINAL, then executes FORMS with *TERMINAL* bound to the terminal, and *TERMINAL-IO* bound to the TERMINAL-IO of the terminal. Finally releases the terminal unless the current thread had exclusive access to it prior to executing WITH-TERMINAL. Returns the values returned by the last of FORMS. macro WITHOUT-TERMINAL (terminal) &body forms => value* If current thread owns TERMINAL, releases it for execution of forms, and then waits to regain ownership. If current thread does not have own the terminal, executed forms without any special processing. Returns the values returned by the last of FORMS. Cheers, -- Nikodemus Schemer: "Buddha is small, clean, and serious." Lispnik: "Buddha is big, has hairy armpits, and laughs." |