Previous Section | Next Chapter | Table of Contents | Glossary | Index |
Returns a list of all lisp processes (threads) known to Clozure CL as of the precise instant it's called. It's safe to traverse this list and to modify the cons cells that comprise that list (it's freshly consed.) Since other threads can create and kill threads at any time, there's generally no way to get an "accurate" list of all threads, and (generally) no sense in which such a list can be accurate.
make-process
name &key
persistent priority class initargs stack-size vstack-size
tstack-size initial-bindings use-standard-initial-bindings
=> process
name---a string, used to identify the process.
persistent---if true, requests that information about the process be retained by SAVE-APPLICATION so that an equivalent process can be restarted when a saved image is run. The default is nil.
priority---ignored. It shouldn't be ignored of course, but there are complications on some platforms. The default is 0.
class---the class of process object to create; should be a subclass of CCL:PROCESS. The default is CCL:PROCESS.
initargs---Any additional initargs to pass to MAKE-INSTANCE. The default is ().
stack-size---the size, in bytes, of the newly-created process's control stack; used for foreign function calls and to save function return address context. The default is CCL:*DEFAULT-CONTROL-STACK-SIZE*.
vstack-size---the size, in bytes, of the newly-created process's value stack; used for lisp function arguments, local variables, and other stack-allocated lisp objects. The default is CCL:*DEFAULT-VALUE-STACK-SIZE*.
tstack-size---the size, in bytes, of the newly-created process's temp stack; used for the allocation of dynamic-extent objects. The default is CCL:*DEFAULT-TEMP-STACK-SIZE*.
use-standard-initial-bindings---when true, the global "standard initial bindings" are put into effect in the new thread before. See DEF-STANDARD-INITIAL-BINDING. "standard" initial bindings are put into effect before any bindings specified by :initial-bindings are. The default is t. This option is deprecated: the correct behavior of many Clozure CL components depends on thread-local bindings of many special variables being in effect.
initial-bindings---an alist of (symbol . valueform) pairs, which can be used to initialize special variable bindings in the new thread. Each valueform is used to compute the value of a new binding of symbol in the execution environment of the newly-created thread. The default is nil.
process---the newly-created process.
Creates and returns a new lisp process (thread) with the specified attributes. process will not begin execution immediately; it will need to be preset (given an initial function to run, as by process-preset) and enabled (allowed to execute, as by process-enable) before it's able to actually do anything.
If valueform is a function, it is called, with no arguments, in the execution environment of the newly-created thread; the primary value it returns is used for the binding of the corresponding symbol.
Otherwise, valueform is evaluated in the execution environment of the newly-created thread, and the resulting value is used.
process---a lisp process (thread).
result---T if process had been runnable and is now suspended; NIL otherwise. That is, T if process's process-suspend-count transitioned from 0 to 1.
Suspends process, preventing it from running, and stopping it if it was already running. This is a fairly expensive operation, because it involves a few calls to the OS. It also risks creating deadlock if used improperly, for instance, if the process being suspended owns a lock or other resource which another process will wait for.
Each call to process-suspend must be reversed by a matching call to process-resume before process is able to run. What process-suspend actually does is increment the process-suspend-count of process.
A process can't suspend itself, though this once worked and this documentation claimed has claimed that it did.
process-suspend was previously called process-disable. process-enable now names a function for which there is no obvious inverse, so process-disable is no longer defined.
process---a lisp process (thread).
result---T if process had been suspended and is now runnable; NIL otherwise. That is, T if process's process-suspend-count transitioned from to 0.
Undoes the effect of a previous call to process-suspend; if all such calls are undone, makes the process runnable. Has no effect if the process is not suspended. What process-resume actually does is decrement the process-suspend-count of process, to a minimum of 0.
This was previously called PROCESS-ENABLE; process-enable now does something slightly different.
process---a lisp process (thread).
result---The number of "outstanding" process-suspend calls on process, or NIL if process has expired.
An "outstanding" process-suspend call is one which has not yet been reversed by a call to process-resume. A process expires when its initial function returns, although it may later be reset.
A process is runnable when it has a process-suspend-count of 0, has been preset as by process-preset, and has been enabled as by process-enable. Newly-created processes have a process-suspend-count of 0.
process---a lisp process (thread).
function---a function, designated by itself or by a symbol which names it.
args---a list of values, appropriate as arguments to function.
result---undefined.
Typically used to initialize a newly-created or newly-reset process, setting things up so that when process becomes enabled, it will begin execution by applying function to args. process-preset does not enable process, although a process must be process-preset before it can be enabled. Processes are normally enabled by process-enable.
process---a lisp process (thread).
timeout---a time interval in seconds. May be any non-negative real number the floor of which fits in 32 bits. The default is 1.
result---undefined.
Tries to begin the execution of process. An error is signaled if process has never been process-preset. Otherwise, process invokes its initial function.
process-enable attempts to synchronize with process, which is presumed to be reset or in the act of resetting itself. If this attempt is not successful within the time interval specified by timeout, a continuable error is signaled, which offers the opportunity to continue waiting.
A process cannot meaningfully attempt to enable itself.
name---a string, used to identify the process. Passed to make-process.
function---a function, designated by itself or by a symbol which names it. Passed to preset-process.
persistent---a boolean, passed to make-process.
priority---ignored.
class---a subclass of CCL:PROCESS. Passed to make-process.
initargs---a list of any additional initargs to pass to make-process.
stack-size---a size, in bytes. Passed to make-process.
vstack-size---a size, in bytes. Passed to make-process.
tstack-size---a size, in bytes. Passed to make-process.
process---the newly-created process.
Creates a lisp process (thread) via make-process, presets it via process-preset, and enables it via process-enable. This means that process will immediately begin to execute. process-run-function is the simplest way to create and run a process.
process---a lisp process (thread).
function---a function.
args---a list of values, appropriate as arguments to function.
result---the result of applying function to args if process is the current-process, otherwise NIL.
Arranges for process to apply function to args at some point in the near future (interrupting whatever process was doing.) If function returns normally, process resumes execution at the point at which it was interrupted.
process must be in an enabled state in order to respond to a process-interrupt request. It's perfectly legal for a process to call process-interrupt on itself.
process-interrupt uses asynchronous POSIX signals to interrupt threads. If the thread being interrupted is executing lisp code, it can respond to the interrupt almost immediately (as soon as it has finished pseudo-atomic operations like consing and stack-frame initialization.)
If the interrupted thread is blocking in a system call, that system call is aborted by the signal and the interrupt is handled on return.
It is still difficult to reliably interrupt arbitrary foreign code (that may be stateful or otherwise non-reentrant); the interrupt request is handled when such foreign code returns to or enters lisp.
It would probably be better for result to always be NIL, since the present behavior is inconsistent.
Process-interrupt works by sending signals between threads, via the C function #_pthread_signal. It could be argued that it should be done in one of several possible other ways under Darwin, to make it practical to asynchronously interrupt things which make heavy use of the Mach nanokernel.
process---a lisp process (thread).
kill-option---an internal argument, must be nil.
result---undefined.
Causes process to cleanly exit from any ongoing computation and enter a state where it can be process-preset. This is implemented by signaling a condition of type PROCESS-RESET; user-defined condition handlers should generally refrain from attempting to handle conditions of this type.
The kill-option argument is for internal use only and should not be specified by user code
A process can meaningfully reset itself.
There is in general no way to know precisely when process has completed the act of resetting or killing itself; a process which has either entered the limbo of the reset state or exited has few ways of communicating either fact. process-enable can reliably determine when a process has entered the "limbo of the reset state", but can't predict how long the clean exit from ongoing computation might take: that depends on the behavior of unwind-protect cleanup forms, and of the OS scheduler.
Resetting a process other than *current-process* involves the use of process-interrupt.
process---a lisp process (thread).
condition---a lisp condition. The default is NIL.
Entirely equivalent to calling (process-interrupt process (lambda () (abort condition))). Causes process to transfer control to the applicable handler or restart for abort.
If condition is non-NIL, process-abort does not consider any handlers which are explicitly bound to conditions other than condition.
The clock resolution of the OS scheduler. Currently, both LinuxPPC and DarwinPPC yield an initial value of 100.
This information is primarily for the benefit of debugging tools. whostate is a terse report on what process is doing, or not doing, and why.
If the process is currently waiting in a call to process-wait or process-wait-with-timeout, its process-whostate will be the value which was passed to that function as whostate.
Advises the OS scheduler that the current thread has nothing useful to do and that it should try to find some other thread to schedule in its place. There's almost always a better alternative, such as waiting for some specific event to occur. For example, you could use a lock or semaphore.
whostate---a string, which will be the value of process-whostate while the process is waiting.
function---a function, designated by itself or by a symbol which names it.
args---a list of values, appropriate as arguments to function.
result---NIL.
Causes the current lisp process (thread) to repeatedly apply function to args until the call returns a true result, then returns NIL. After each failed call, yields the CPU as if by process-allow-schedule.
As with process-allow-schedule, it's almost always more efficient to wait for some specific event to occur; this isn't exactly busy-waiting, but the OS scheduler can do a better job of scheduling if it's given the relevant information. For example, you could use a lock or semaphore.
whostate---a string, which will be the value of process-whostate while the process is waiting.
ticks---either a positive integer expressing a duration in "ticks" (see *ticks-per-second*), or NIL.
function---a function, designated by itself or by a symbol which names it.
args---a list of values, appropriate as arguments to function.
result---T if process-wait-with-timeout returned because its function returned true, or NIL if it returned because the duration ticks has been exceeded.
If ticks is NIL, behaves exactly like process-wait, except for returning T. Otherwise, function will be tested repeatedly, in the same kind of test/yield loop as in process-wait until either function returns true, or the duration ticks has been exceeded.
Having already read the descriptions of process-allow-schedule and process-wait, the astute reader has no doubt anticipated the observation that better alternatives should be used whenever possible.
Executes body in an environment in which process-interrupt requests are deferred. As noted in the description of process-interrupt, this has nothing to do with the scheduling of other threads; it may be necessary to inhibit process-interrupt handling when (for instance) modifying some data structure (for which the current thread holds an appropriate lock) in some manner that's not reentrant.
Executes body in an environment in which process-interrupt requests have immediate effect.
name---any lisp object; saved as part of lock. Typically a string or symbol which may appear in the process-whostates of threads which are waiting for lock.
lock---a newly-allocated object of type CCL:LOCK.
lock---an object of type CCL:LOCK.
body---an implicit progn.
result---the primary value returned by body.
Blocks until lock is owned by the calling thread.
The macro with-lock-grabbed could be defined in terms of grab-lock and release-lock, but it is actually implemented at a slightly lower level.
lock---an object of type CCL:LOCK.
result---T if lock has been obtained, or NIL if it has not.
Tests whether lock can be obtained without blocking - that is, either lock is already free, or it is already owned by *current-process*. If it can, causes it to be owned by the calling lisp process (thread) and returns T. Otherwise, the lock is already owned by another thread and cannot be obtained without blocking; NIL is returned in this case.
Creates and returns an object of type CCL::READ-WRITE-LOCK. A read-write lock may, at any given time, belong to any number of lisp processes (threads) which act as "readers"; or, it may belong to at most one process which acts as a "writer". A read-write lock may never be held by a reader at the same time as a writer. Initially, read-write-lock has no readers and no writers.
read-write-lock---an object of type CCL:READ-WRITE-LOCK.
body---an implicit progn.
result---the primary value returned by body.
Waits until read-write-lock has no writer, ensures that *current-process* is a reader of it, then executes body.
After executing body, if *current-process* was not a reader of read-write-lock before with-read-lock was called, the lock is released. If it was already a reader, it remains one.
read-write-lock---an object of type CCL:READ-WRITE-LOCK.
body---an implicit progn.
result---the primary value returned by body.
Waits until read-write-lock has no readers and no writer other than *current-process*, then ensures that *current-process* is the writer of it. With the lock held, executes body.
After executing body, if *current-process* was not the writer of read-write-lock before with-write-lock was called, the lock is released. If it was already the writer, it remains the writer.
semaphore---an object of type CCL:SEMAPHORE.
result---an integer representing an error identifier which was returned by the underlying OS call.
Atomically increments semaphore's "count" by 1; this may enable a waiting thread to resume execution.
semaphore---an object of type CCL:SEMAPHORE.
result---an integer representing an error identifier which was returned by the underlying OS call.
Waits until semaphore has a positive count that can be atomically decremented; this will succeed exactly once for each corresponding call to SIGNAL-SEMAPHORE.
semaphore---An object of type CCL:SEMAPHORE.
timeout---a time interval in seconds. May be any non-negative real number the floor of which fits in 32 bits. The default is 1.
result---T if timed-wait-on-semaphore returned because it was able to decrement the count of semaphore; NIL if it returned because the duration timeout has been exceeded.
fd---a file descriptor, which is a non-negative integer used by the OS to refer to an open file, socket, or similar I/O connection. See ccl::stream-device.
timeout---either NIL or a time interval in milliseconds. Must be a non-negative integer. The default is NIL.
Wait until input is available on fd. This uses the select() system call, and is generally a fairly efficient way of blocking while waiting for input. More accurately, process-input-wait waits until it's possible to read from fd without blocking, or until timeout, if it is not NIL, has been exceeded.
Note that it's possible to read without blocking if the file is at its end - although, of course, the read will return zero bytes.
process-input-wait has a timeout parameter, and process-output-wait does not. This inconsistency should probably be corrected.
fd---a file descriptor, which is a non-negative integer used by the OS to refer to an open file, socket, or similar I/O connection. See ccl::stream-device.
timeout---either NIL or a time interval in milliseconds. Must be a non-negative integer. The default is NIL.
Wait until output is possible on fd or until timeout, if it is not NIL, has been exceeded. This uses the select() system call, and is generally a fairly efficient way of blocking while waiting to output.
If process-output-wait is called on a network socket which has not yet established a connection, it will wait until the connection is established. This is an important use, often overlooked.
process-input-wait has a timeout parameter, and process-output-wait does not. This inconsistency should probably be corrected.
Controls how attempts to obtain ownership of terminal input are made. When NIL, a message is printed on *TERMINAL-IO*; it's expected that the user will later yield control of the terminal via the :Y toplevel command. When T, a BREAK condition is signaled in the owning process; continuing from the break loop will yield the terminal to the requesting process (unless the :Y command was already used to do so in the break loop.)
p---a lisp process (thread), designated either by an integer which matches its process-serial-number, or by a string which is equal to its process-name.
:Y is a toplevel command, not a function. As such, it can only be used interactively, and only from the initial process.
The command yields control of terminal input to the process p, which must have used with-terminal-input to request access to the terminal input stream.
process---a process, typically created by process-run-function or by make-process
default---A default value to be returned if the specified process doesn't exit normally.
values---The values returned by the specified process's initial function if that function returns, or the value of the default argument, otherwise.
Waits for the specified process to terminate. If the process terminates "normally" (if its initial function returns), returns the values that that initial function returnes. If the process does not terminate normally (e.g., if it's terminated via process-kill and a default argument is provided, returns the value of that default argument. If the process doesn't terminate normally and no default argument is provided, signals an error.
A process can't successfully join itself, and only one process can successfully receive notification of another process's termination.
Previous Section | Next Chapter | Table of Contents | Glossary | Index |