5 The Multitasking Facility
Syntax:*all-processes*
*all-processes*
contains a list of all the processes that currently exist.
> *all-processes* (#<Process Initial 79F40B> #<Process Idle 79F463>)check-stack-remaining Function
Syntax:check-stack-remaining
words
check-stack-remaining
checks the remaining stack space. If there are fewer words of stack space remaining than are specified, the function creates a new process and enters the Debugger in that process.
get-stack-remaining
to find the number of words of remaining stack space on the current process's stack.
> (check-stack-remaining 100) NIL> (check-stack-remaining 10000000) ; an absurdly large number >>Error: #<Process Initial 6D0123> couldn't obtain needed 10000000 words of stack-space INVOKE-DEBUGGER: Required arg 0 (CONDITION): #<Condition SIMPLE-ERROR 92BD7B> 0: Abort to top level in #<Process Initial 6D0123> 1: Enter debugger in #<Process Initial 6D0123>; clobber more stack space 2: Kill process #<Process Stack problems 92BAB3> 3: Restart process #<Process Stack problems 92BAB3>
-> 0 Abort to top level in #<Process Initial 6D0123> Back to Lisp Top Level
get-stack-remaining
Syntax: *current-process*
*current-process*
contains the process that is currently running.
process-wait
or process-wait-with-timeout
, the process's wait function is always evaluated with*current-process*
bound to the waiting process.
> *current-process* #<Process Initial 79F40B>deactivate-process Function> (defun newtask () (setq *temp* *current-process*)) NEWTASK
> (make-process :name "Newtask" :function 'newtask :stack-size 1000) #<Process Newtask 79FBE3>
> *temp* #<Process Newtask 79FBE3>
Syntax:deactivate-process
process
Syntax:activate-process
process
deactivate-process
prevents a specified process from running until the functionactivate-process
is invoked with the process as an argument.
activate-process
allows a process to run that has been stopped by a call todeactivate-process
.
> (defvar *wake-up-subprocess* nil) *WAKE-UP-SUBPROCESS*get-stack-remaining Function> (defun work () (loop (process-wait "Wakeup call" 'symbol-value '*wake-up-subprocess*) (format t "I am awake.~%") (setf *wake-up-subprocess* nil))) WORK
> (setf subprocess (make-process :name "example" :function 'work)) #<Process example 61353B>
> (setf *wake-up-subprocess* t) T I am awake.
> (deactivate-process subprocess) #<Process example 61353B>
> (setf *wake-up-subprocess* t) T
> (activate-process subprocess) #<Process example 61353B> I am awake.
Syntax:get-stack-remaining
&optional
stack-group
get-stack-remaining
returns the number of words of stack space that can be used before the stack will overflow.
check-stack-remaining
Syntax:*inhibit-scheduling*
*inhibit-scheduling*
ist
if process switching is currently inhibited; otherwise, it isnil
.
with-scheduling-inhibited
andwith-scheduling-allowed
prevent and allow the scheduler to switch processes respectively.
> *inhibit-scheduling* NIL> (with-scheduling-inhibited *inhibit-scheduling*) T
with-scheduling-inhibited
, with-scheduling-allowed
Syntax:*initial-io*
*initial-io*
stores the value of the stream that communicates with the user when normal stream input and output has failed or when the scheduler encounters an internal error. This stream must be able to work without scheduling. Generally, the interaction stream that was opened when Lisp started up is used.
> (eq *initial-io* *terminal-io*) T> *initial-io* #<Stream SPLIT-STREAM 69DA3B>
using-initial-io
Syntax:*initial-process*
*initial-process*
contains the initial process, which is the process that exists when Lisp is first started.
> *initial-process* #<Process Initial 79F40B>interrupt-process Function
Syntax:interrupt-process
process function&rest
args
interrupt-process
interrupts the execution of a specified process and invokes a specified function. The process resumes its previous computation when the interruption returns.
interrupt-process
.
throw
.with-interruptions-allowed
.process-wait
or to a related function, the process wakes up to perform the interruption. If the interruption exits normally, the process resumes waiting. If the interruption performs athrow
to a tag outside ofprocess-wait
, the process performs the throw normally and does not return to its waiting state.
> (defun sleep-until-throw () (catch 'wakeup (process-wait-forever "Asleep"))) SLEEP-UNTIL-THROW> (setf sleeper (make-process :name "sleeper" :function 'sleep-until-throw)) #<Process sleeper 6C3DFB>
> (process-whostate sleeper) "Asleep" (progn (interrupt-process sleeper #'(lambda () (format t "I am process ~A~%" *current-process*))) (sleep 5)) I am process #<Process sleeper 6C3DFB> NIL
> (process-whostate sleeper) "Asleep"
> (interrupt-process sleeper #'(lambda () (throw 'wakeup nil))) #<Process sleeper 6C3DFB>
> (process-whostate sleeper) "Dead"
with-interruptions-allowed
,with-interruptions-inhibited
Syntax:*keyboard-interrupt-process*
*keyboard-interrupt-process*
contains the process that should receive the interruption when a keyboard interrupt character is typed.
with-keyboard-interrupt
changes the value of the interrupt process during the execution of the specified forms.
> *keyboard-interrupt-process* #<Process Initial 6A219B>
with-keyboard-interrupt-process
Syntax:kill-process
process&key :suppress-unwind-protects
kill-process
runs the specified process, executes cleanup forms, kills the process, and returns its resources. The process cannot be restarted.
kill-process
.
:suppress-unwind-protects
keyword argument isnil
, cleanup forms inside of the process that are introduced by the Common Lisp special formunwind-protect
are executed before the process is killed; this value is the default.
nil
value, the function kills the specified process without running it and disposes of its resources immediately. This method of killing a process is dangerous and should only be used as a last resort when a more reasonable method will not work. Files in the process are not closed, locks are not released, and all other details of process cleanup are lost forever.
> (defun job () (unwind-protect (process-wait-forever) (format t "Unwind the stack of process ~A~%" *current-process*))) JOBlet-globally Macro> (setf job1 (make-process :name "job1" :function 'job)) #<Process job1 6C239B>
> (progn (kill-process job1) (process-allow-schedule)) Unwind the stack of process #<Process job1 6C239B> T
> (setf job2 (make-process :name "job2" :function 'job)) #<Process job2 6C265B>
> (progn (kill-process job2 :suppress-unwind-protects t) (process-allow-schedule)) T
Syntax:let-globally
({var | (var value)}*) {declaration}* {form}*
let-globally
creates new variables and then uses the Common Lisp special formsetq
to set the values of those variables. It executes a series of forms and then uses the special formunwind-protect
to restore the variable bindings that were in effect before the macro call.
nil
. If you use the list (var value) but do not specify a value for the var argument, a warning is signaled.
let-globally
is the value or values returned by the last form that is executed. If there are no form arguments,nil
is returned.
declare
.
> (defparameter *a* 100) *A* > (defun work () (let-globally ((*a* 120)) (process-wait-forever))) WORKmake-process Function> (setq subprocess (make-process :name "work" :function 'work)) #<Process work 615BF3>
> *a* 120
> (kill-process subprocess) #<Process work 615BF3>
> *a* 100
make-process
&key :name :function :args :stack-size :priority :wait-function :wait-args :restart-action
make-process
creates and returns a process.
make-process
::name
:function
:args
:stack-size
nil
, the default stack size is 5000 32-bit words.
:priority
:wait-function
nil
value when applied to its arguments before the scheduler can run the process associated with it. If this keyword argument is omitted, the scheduler runs the process.
:wait-args
:restart-action
:flush
means that this process will not exist in the saved image; this value is the default.:restart
means that the process will run its initial function again when the image is restarted.disksave
save the current state of a running process.
make-process
. If the initial function returns, the scheduler kills the process by invoking the functionkill-process
.
;; The function SET-ALARM creates a process that prints a given ;; message at a given time. The message is printed to the stream ;; that is the value of *TERMINAL-IO* when SET-ALARM is called. ;; This stream is passed as an argument to the initial function of ;; the process. > (defun set-alarm (universal-time message) "Sets an alarm for the given time" (make-process :name "Alarm" :stack-size 3000 :function #'alarm-top-level :args (list *terminal-io* universal-time message))) SET-ALARM;; This is the top-level function of the alarm process. It ;; determines how much time remains until the alarm goes off, and ;; then it goes to sleep. > (defun alarm-top-level (*terminal-io* utime message) (let* ((now (get-universal-time)) (time (- utime now))) (sleep time) (format t "~&[~A]~%" message))) ALARM-TOP-LEVEL
kill-process
process-in-the-debugger-p Function
Syntax:process-active-p
process
Syntax:process-alive-p
process
Syntax:process-in-the-debugger
process
process-active-p
is true if its process argument is active; otherwise, it is false. A process is active if an invocation of the functionprocess-state
for the process returns:active
.process-alive-p
is true if its process argument is alive; otherwise, it is false. A process is alive if an invocation of the functionprocess-state
for the process returns:active
or:inactive
.process-in-the-debugger-p
is true if its process argument is in the Debugger; otherwise, it is false.
> (defun laziness () (process-wait-forever "Snore")) LAZINESS> (setq lazy-process (make-process :name "Lazy" :function 'laziness)) #<Process Lazy 6EE9FB>
> (and (process-active-p lazy-process) (process-alive-p lazy-process)) T
> (process-alive-p lazy-process) T
> (deactivate-process lazy-process) #<Process Lazy 6EE9FB>
> (process-active-p lazy-process) NIL
> (process-alive-p lazy-process) T
> (kill-process lazy-process) #<Process Lazy 6EE9FB>
> (or (process-active-p lazy-process) (process-alive-p lazy-process)) NIL
> (process-in-the-debugger-p *current-process*) NIL
> (error "An error") >>Error: An error
EVAL: Required arg 0 (EXPRESSION): (ERROR "An error") :A 0: Abort to Lisp Top Level -> (process-in-the-debugger-p *current-process*) T ->
process-state
Syntax: process-allow-schedule
process-allow-schedule
suspends the current process for one scheduler cycle to allow other processes to run.
Syntax:process-lock
place&optional
lock-value action wait-state
Syntax:process-unlock
place&optional
lock-value action
Syntax:with-process-lock
(place &optional
lock-value&key
:action :wait-state :flag
) {form}*
process-lock
,process-unlock
, andwith-process-lock
provide a conventional interface for preventing data shared among multiple processes from being modified by more than one process at a time.
setf
; this location can contain any Lisp value. If the value of place isnil
, the lock is considered to be a free lock. If place has any non-nil
value, it is considered to be a locked lock.
*current-process*
.
process-lock
, the wait-state optional argument is a Lisp string that is used as a whostate argument to the functionprocess-wait
. This string is displayed as the state of the process.
process-lock
attempts to lock the location specified by place as follows:process-lock
returnsnil
. While place is locked, no other process should modify data covered by the lock.t
and exits.process-lock
to distinguish between the case where place is free and the case where place is already locked by the process specified in the lock-value argument. If you found the lock to be free, you can safely unlock it, while if you found it locked, you might want to let it be unlocked by the enclosing context.:wait
(the default), the macro attempts to callprocess-wait
to suspend the current process until place isnil
. If scheduling is inhibited or interruptions are deferred, an error is signaled by such a call.:abort
, the macro immediately returnsnil
and exits.:abort-on-deadlock
, the lock is held by another process and waiting would produce a detectable deadlock. The body is not run andnil
is returned. Deadlocks are detectable when scheduling is inhibited or interrupts are deferred; waiting in this case would be an error.process-wait-with-timeout
is called with this integer as the number of seconds to wait before aborting.process-unlock
attempts to free the location specified by the place argument. If the value of the place argument is lock-value, the macro frees the lock by changing the value tonil
. The optional action argument to process-unlock
specifies what happens when the value of the place argument is not lock-value; this argument can have one of the following values::ignore
process-unlock
returns the message:lock-not-locked
or:locked-by-different-process
to describe the current state of the lock.
:cerror
process-unlock
has exited, you should not rely on these values to always reflect the current state of the system.
with-process-lock
temporarily locks a location specified by place, evaluates the form arguments, and then frees the place location. The action that is taken depends on the value of the:action
keyword argument as follows::wait
(the default) and the lock was previously seized by this process,with-process-lock
simply executes the body. Ifprocess-unlock
is called by one of the form arguments, the lock is freed immediately, and no error is signaled whenwith-process-lock
exits. It simply returns the result of evaluating the last form argument in the body.:abort
and the lock is held by another process, the body is not executed andnil
is returned.:abort-on-deadlock
, then the behavior is the same as with:wait,
except in the case of detectable deadlock, in which case the behavior is the same as with:abort
. Deadlocks are detectable when scheduling is inhibited, as withwith-scheduling-inhibited
, or interrupts are deferred, as withwith-interruptions-inhibited
.:action
argument is an integer, thenprocess-wait-with-timeout
is called with this integer as the number of seconds to wait before aborting.
:wait-state
keyword argument towith-process-lock
is a Lisp string that is used as a whostate argument to the functionprocess-wait
. This string displays the state of the process.
:flag
keyword argument is used to signal whether the process is acquiring this lock for the first time (as opposed to already owning it). The:flag
keyword argument is a symbol which is used as a variable to be locally bound over the execution of the body ofwith-process-lock
. The variable is true if this is a newly acquired lock.
;;; The following safe deposit example uses locks to ensure the ;;; consistency of the accounts and thus to prevent errors:process-name Function> (defun safe-deposit (amount account)
;; This lock prevents the race between reading the balance and ;; writing the new balance. (with-process-lock ((account-lock account)) (incf (account-balance account) amount))) SAFE-DEPOSIT> (defun safe-withdraw (amount account) ;; This lock prevents the race between reading the balance and ;; writing the new balance. (with-process-lock ((account-lock account)) (decf (account-balance account) amount))) SAFE-WITHDRAW
;;; SAFE-TRANSFER must lock both accounts before updating either. ;;; To avoid deadlocks, it locks the accounts in order. In ;;; addition, interruptions must be inhibited so that the update ;;; completes. > (defun safe-transfer (amount from-account to-account) (if (< (account-number from-account) (account-number to-account)) ;; From account has a lower number. (with-process-lock ((account-lock from-account)) (with-process-lock ((account-lock to-account)) (with-interruptions-inhibited (safe-withdraw amount from-account) (safe-deposit amount to-account)))) ;; To account has a lower number. (with-process-lock ((account-lock to-account)) (with-process-lock ((account-lock from-account)) (with-interruptions-inhibited (safe-withdraw amount from-account) (safe-deposit amount to-account)))))) SAFE-TRANSFER
> (defun safe-transfer-random (account1 account2) (if (zerop (random 2)) (safe-transfer (random 20) account1 account2) (safe-transfer (random 20) account2 account1))) SAFE-TRANSFER-RANDOM
;;; To be certain that processes are not in a critical section, ;;; this function interrupts the processes to get them to kill ;;; themselves. (This precaution isn't necessary in this example ;;; because there is no critical code outside the locked regions, ;;; but it is good form.) > (defun test-safe () (let ((peters-account (make-account :Balance 100)) (pauls-account (make-account :Balance 100)) (*scheduling-quantum* 10)) (let (p1 p2) (unwind-protect (progn (setq p1 (make-process :name "transfer1" :function #'(lambda () (loop (safe-transfer-random peters-account pauls-account)))) p2 (make-process :name "transfer2" :function #'(lambda () (loop (safe-transfer-random pauls-account peters-account))))) (process-wait-with-timeout "sleep" 5 #'(lambda () nil)))
;; Since peters-account is created before pauls-account ;; it must have a lower number. (with-process-lock ((account-lock peters-account)) (with-process-lock ((account-lock pauls-account)) (when p1 (interrupt-process p1 #'(lambda () (kill-process p1)))) (when p2 (interrupt-process p2 #'(lambda () (kill-process p2))))))) (format t "~%Total $~d." (+ (account-balance peters-account) (account-balance pauls-account)))))) TEST-SAFE
> (loop (test-safe)) Total $200. Total $200. Total $200. Total $200. Total $200. Total $200. Total $200. Total $200. Total $200. Total $200. ...
;;; The following examples deal with various attempts to unlock ;;; a process. ;;; ;;; The default action for PROCESS-UNLOCK is to signal an error ;;; if the lock is not already locked. ;;; > (setq *my-place* nil) NIL
> (process-unlock *my-place*) >>Error: Attempting to unlock a lock that isn't locked.
;;; Here's how we could have safely unlocked the lock: > (process-unlock *my-place* *current-process* :ignore) :LOCK-NOT-LOCKED >
;;; WITH-PROCESS-LOCK does the work of locking and unlocking ;;; the process for you. However, you may choose to unlock the ;;; lock prematurely, within the body of WITH-PROCESS-LOCK. > (setq *my-place* nil) NIL
> (with-process-lock (*my-place*) (process-unlock *my-place*) (print "here")) "here" "here" >
;;; Finally, we illustrate the use of the :flag keyword argument ;;; to WITH-PROCESS-LOCK. ;;; We use the :flag keyword argument to see whether some ;;; enclosing context has already grabbed the lock. ;;; If so, we won't try to unlock the lock early. ;;; If we are freshly grabbing the lock, then we can safely ;;; unlock it, which we might want to do to make it available ;;; as soon as possible.
> (defun hurry-up-and-wait () (with-process-lock (*my-place* *CURRENT-PROCESS* :action :abort :flag not-already-grabbed-p) (if not-already-grabbed-p (progn (print "I grabbed the lock!") (print "I might as well unlock it early.") (process-unlock *my-place*)) (progn (print "I didn't freshly grab this lock.") (print "I better not unlock it."))) (print "Imagine this part taking a long time.") nil)) HURRY-UP-AND-WAIT
> (hurry-up-and-wait) "I didn't freshly grab this lock." "I better not unlock it." "Imagine this part taking a long time." NIL
> (process-lock *my-place*) T
> (hurry-up-and-wait) "I didn't need to grab the lock." "I better not unlock it." "Imagine this part taking a long time." NIL >
process-initial-function Function
process-initial-arguments Function
process-wait-function Function
process-wait-arguments Function
process-interruptions Function
Syntax:process-name
process
Syntax:process-state
process
Syntax:process-whostate
process
Syntax:process-initial-function
process
Syntax:process-initial-arguments
process
Syntax:process-wait-function
process
Syntax:process-wait-arguments
process
Syntax:process-interruptions
process
process-name
returns a string that was given as the name argument tomake-process
when the process was created.
process-state
returns one of the following keywords to describe the current state of the process::active
:inactive
deactivate-process
.
:killed
kill-process
.
process-whostate
returns a string that describes the current state of the process. If the process state is:killed
, the string"Killed"
is returned. If the process state is:active
or:inactive
, the function returns one of the following values:process-wait
,process-wait-forever
, orprocess-wait-with-timeout
"Run"
if the process is running or is currently able to runprocess-initial-function
returns the function specified as the:function
keyword argument tomake-process
when the process was created. This function is called the initial function, and it is the first function to call the process.
process-initial-arguments
returns a list of the arguments to the initial function for the process.
process-wait-function
returns the function specified by the wait-function argument to eitherprocess-wait
,process-wait-forever
, orprocess-wait-with-timeout
.
process-wait-arguments
returns any arguments to the wait function specified in eitherprocess-wait
,process-wait-forever
, orprocess-wait-with-timeout
.
process-interruptions
returns a list of the interruptions pending for the specified process. Each element of the list is a list whose car is the interruption function and whose cdr is the list of arguments to that function.
setf
with all of these functions; however, no error checking is performed, and errors can seriously damage the scheduler.
> (defun newtask-work (x) (loop (process-wait "Non-NIL" 'symbol-value x) (format t "~&~S has value ~S~%" x (symbol-value x)) (set x nil))) NEWTASK-WORK> (defvar *temp* nil) *TEMP*
> (setq process (make-process :name "Newtask" :function 'newtask-work :args '(*temp*) :stack-size 1000)) #<Process Newtask 7A1FF3>
> (process-name process) "Newtask"
> (process-state process) :ACTIVE
> (process-whostate process) "Non-NIL"
> (process-initial-function process) NEWTASK-WORK
> (process-initial-arguments process) (*TEMP*)
> (process-wait-function process) SYMBOL-VALUE
> (process-wait-arguments process) (*TEMP*)
> (setf (process-name process) "New Newtask") "New Newtask"
> process #<Process New Newtask 7A1FF3>
> (setq lazy-process (make-process :name "lazy" :function 'process-wait-forever)) #<Process lazy 61982B>
> (with-scheduling-inhibited (interrupt-process lazy-process #'format t "I'm interrupted~%") (process-interruptions lazy-process)) ((#<Compiled-Function FORMAT 1DBDEF> T "I'm interrupted~%")) I'm interrupted
make-process
Syntax:processp
object
processp
is true if its object argument is a process; otherwise, it is false.
> (processp *current-process*) Tprocess-plist Function> (processp 26) NIL
Syntax:process-plist
process
process-plist
accesses the property list that is associated with the specified process.
getf
.
> (setf (process-plist *initial-process*) '(type initial other-name "initial process")) (TYPE INITIAL OTHER-NAME "initial process")process-suspend-functions Function> (getf (process-plist *initial-process*) 'type) INITIAL
> (setf (getf (process-plist *initial-process*) 'color) 'green) GREEN
> (process-plist *initial-process*) (COLOR GREEN TYPE INITIAL OTHER-NAME "initial process")
process-resume-functions Function
Syntax:process-suspend-functions
process
Syntax:process-resume-functions
process
process-suspend-functions
returns a list of functions that are executed just before the scheduler switches from the specified process to a new process.
process-resume-functions
returns a list of functions that are executed before the scheduler switches to the specified process.
setf
to modify this list.
> (setf lazy-process (make-process :name "Lazy" :function #'process-wait-forever)) #<Process Lazy 970156>process-wait Function> (defun resume-function () (format t "~&Resuming ~S~%" *current-process*)) RESUME-FUNCTION
> (push 'resume-function (process-resume-functions lazy-process)) (RESUME-FUNCTION)
> (push #'(lambda () (format t "~&Suspending process ~S~%" *current-process*)) (process-suspend-functions lazy-process)) (#<Interpreted-Function (LAMBDA NIL (FORMAT T "~&Suspending process ~S~%" *CURRENT-PROCESS*)) 976206>) > (interrupt-process lazy-process #'ignore nil) #<Process Lazy 970156>
> Resuming #<Process Lazy 970156> Suspending process #<Process Lazy 970156>
process-wait-with-timeout Function
Syntax:process-wait
whostate function&rest
args
Syntax:process-wait-with-timeout
whostate seconds function&rest
args
Syntax:process-wait-forever
&optional
whostate
process-wait
suspends the current process until its function argument returns a non-nil
value when applied to args; the non-nil
value is returned.process-wait-with-timeout
suspends the current process until one of the following events occurs:nil
value when applied to args; in this case, the non-nil
value is returned.nil
is returned.process-wait-forever
suspends the current process and never returns.process-wait-forever
, the default value is"Wait Forever"
.
process-wait-with-timeout
is a numeric value that specifies the number of seconds to wait.
process-wait
,process-wait-with-timeout
, or process-wait-forever
; at this time, process scheduling is inhibited. If the function that was invoked immediately returns a non-nil
value, no processes are switched, and the calling process does not wait.
*current-process*
is bound to the process whose wait function is being called. Thus, the wait function can find out the value of a special variable in its process by using the functionsymbol-process-value
.
interrupt-process
is used to execute a Common Lispthrow
to a tag outside of the function that suspended the process.
process-wait
,process-wait-with-timeout
, orprocess-wait-forever
when scheduling is inhibited.
Syntax:*quitting-lisp*
*quitting-lisp*
has a non-nil
value when any process has called the functionquit
; otherwise, its value isnil
.
*quitting-lisp*
is non-nil
, no new processes can be created, and no process can be deactivated.
(defmacro dont-let-x-change (&body body) '(unwind-protect (progn ,@body) (when (and (did-x-change) (y-or-n-p "Shall I set X back?")) (restore-x))))
quit
, you receive the"Shall I set X back?"
query. Since you are quitting Lisp, you can prevent the query with the following modified version of the code:
(defmacro dont-let-x-change (&body body) '(unwind-protect (progn ,@body) (unless *quitting-lisp* (when (and (did-x-change) (y-or-n-p "Shall I set X back?")) (restore-x)))))restart-process Function> *quitting-lisp* NIL
> (unwind-protect (quit) (format t "~&The value of *quitting-lisp* is ~A~2%" *quitting-lisp*)) The value of *quitting-lisp* is T
Syntax:restart-process
process
restart-process
restarts a specified process.
unwind-protect
. Then it reapplies its initial function, which was specified when the process was created, to its initial arguments.
> (setq *a* 0) 0*scheduling-quantum* Variable> (setq silly-process (make-process :name "silly" :function #'(lambda () (incf *a*) (process-wait-forever)))) #<Process silly 6C2DDB>
> *a* 1
> (restart-process silly-process) #<Process silly 6C2DDB>
> *a* 2
Syntax:*scheduling-quantum*
*scheduling-quantum*
contains the amount of time in milliseconds that a process can run before the scheduler interrupts it to run new processes.
Syntax:show-processes
show-processes
prints information about every process, including the current status of each process.
*standard-output*
.
> (show-processes) * #<Process Initial 632F6B> "Run" state ACTIVE wait-fn TRUE initial-fn NIL #<Process Idle 632FC3> "Run" state ACTIVE wait-fn TRUE initial-fn IDLE-TOP-LEVEL NILsymbol-global-value Function> (defun do-nothing () (process-wait-forever)) DO-NOTHING > (make-process :name "Do Nothing" :function 'do-nothing) #<Process Do Nothing 6891EB>
> (show-processes) #<Process Do Nothing 6891EB> "Wait Forever" state ACTIVE wait-fn FALSE initial-fn DO-NOTHING * #<Process Initial 632F6B> "Run" state ACTIVE wait-fn TRUE initial-fn NIL #<Process Idle 632FC3> "Run" state ACTIVE wait-fn TRUE initial-fn IDLE-TOP-LEVEL NIL
Syntax:symbol-global-value
symbol
symbol-global-value
returns the global value of the variable associated with the specified symbol; it ignores any values for the symbol that are dynamically bound in processes. An error is signaled if the variable is unbound.
symbol-global-boundp
to test whether the symbol has an associated value.
setf
with this function to modify the specified symbol.
> (defvar *temp* 100) *TEMP*> (let ((*temp* 120)) (format t "*temp*'s dynamic value is ~D; global value is ~D~%" *temp* (symbol-global-value '*temp*))) *temp*'s dynamic value is 120; global value is 100 NIL
symbol-global-boundp
symbol-process-boundp Function
symbol-dynamically-boundp Function
Syntax:symbol-global-boundp
symbol
Syntax:symbol-process-boundp
symbol process
Syntax:symbol-dynamically-boundp
symbol&optional process
symbol-global-boundp
is true if its symbol argument has a global value; otherwise, it is false.symbol-process-boundp
is true if its symbol argument has a value in the given process; otherwise, it is false.symbol-dynamically-boundp
is true if its symbol argument is dynamically bound inside the given process; it is false if the process has no dynamic bindings for the symbol.
*current-process*
is used.
> (defun describe-bindings (symbol proc) (format t "Global ~A, process ~A, dynamically ~A" (symbol-global-boundp symbol) (symbol-process-boundp symbol proc) (symbol-dynamically-boundp symbol proc))) DESCRIBE-BINDINGS> (defvar *a* t) *A*
> (describe-bindings '*a* *current-process*) Global T, process T, dynamically NIL NIL
> (let ((*a* t)) (describe-bindings '*a* *current-process*)) Global T, process T, dynamically T NIL
> (let ((*a* t)) (makunbound '*a*) (describe-bindings '*a* *current-process*)) Global T, process NIL, dynamically T NIL
> (makunbound '*a*) *A*
> (describe-bindings '*a* *current-process*) Global NIL, process NIL, dynamically NIL NIL
> (let ((*a* t)) (describe-bindings '*a* *current-process*)) Global NIL, process T, dynamically T NIL
> (let ((*a* t)) (makunbound '*a*) (describe-bindings '*a* *current-process*)) Global NIL, process NIL, dynamically T NIL
symbol-global-value
, symbol-process-value
Syntax:symbol-process-value
symbol process
symbol-process-value
returns the global or dynamic value of the variable associated with the specified symbol as if the given process were current. If the symbol is not bound in the process, the function returns the global value. An error is signaled if the variable is unbound.
symbol-process-boundp
to test whether the symbol has an associated value.
setf
with this function to modify the specified symbol in the process.
> (proclaim '(special *a*)) T> (defun waiter () (let ((*a* 20)) (process-wait-forever))) WAITER
> (setq waiter (make-process :name "WAITER" :function 'waiter)) #<Process WAITER 60F333>
> (symbol-process-value '*a* waiter) 20
> (setf (symbol-process-value '*a* waiter) 25) 25
> (interrupt-process waiter #'(lambda () (format t "*a* has value ~D~%" *a*))) #<Process WAITER 60F333> *a* has value 25
symbol-process-boundp
Syntax:using-initial-io
{form}*
using-initial-io
disables the scheduler during the execution of its form arguments and binds the Common Lisp variable*terminal-io*
to the value specified by the variable*initial-io*
.
> (using-initial-io (error "Things are really messed up badly.")) >>Error: Things are really messed up badly.EVAL: Required arg 0 (EXPRESSION): (USING-INITIAL-IO (ERROR "Things are really messed up badly.")) :A 0: Abort to Lisp Top Level -> :a Abort to Lisp Top Level Back to Lisp Top Level
*initial-io*
with-interruptions-inhibited Macro
Syntax:with-interruptions-allowed
{form}*
Syntax:with-interruptions-inhibited
{form}*
with-interruptions-allowed
and with-interruptions-inhibited
specify whether a process can be interrupted.
with-interruptions-allowed
allows interruptions to occur during the execution of the form arguments; it locally suppresses the effect ofwith-interruptions-inhibited
.
with-interruptions-inhibited
prevents a process from being interrupted so that the specified form arguments can execute normally.
with-interruptions-inhibited
eventually run to completion within normal scheduling unless an error occurs. You cannot interrupt the execution of the forms from outside of the body of the macro.
with-interruptions-inhibited
are deferred until the execution of the form arguments is complete.
> (with-interruptions-inhibited (interrupt-process *current-process* #'format t "Running the interruption~%") (format t "I am at point A~&") (with-interruptions-allowed (format t "I am at point B~&")) (format t "I am at point C~&")) I am at point A Running the interruption I am at point B I am at point C NIL
interrupt-process
Syntax:with-keyboard-interrupt-process
process {form}*
with-keyboard-interrupt-process
sets the variable*keyboard-interrupt-process*
to the given process and executes the form arguments.
*keyboard-interrupt-process*
is restored if its value has not changed; otherwise, the new value of*keyboard-interrupt-process*
is kept.
*keyboard-interrupt-process*
with-scheduling-inhibited Macro
Syntax:with-scheduling-allowed
{form}*
Syntax:with-scheduling-inhibited
{form}*
with-scheduling-allowed
andwith-scheduling-inhibited
determine whether the scheduler can block a process.
with-scheduling-allowed
allows the scheduler to switch processes during the execution of the form arguments; it locally suppresses the effect ofwith-scheduling-inhibited
.
with-scheduling-inhibited
prohibits the scheduler from switching processes during the execution of the form arguments.
with-scheduling-inhibited
signal an error.
Generated with Harlequin WebMaker