mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
399 lines
14 KiB
Plaintext
399 lines
14 KiB
Plaintext
@c Generated by the sb-manual contrib. Do not edit.
|
|
|
|
@node package locks
|
|
@cindex package lock
|
|
@cindex lock, package
|
|
@chapter Package Locks
|
|
|
|
@menu
|
|
* Package Lock Concepts: package lock concepts.
|
|
* Package Lock Dictionary: package lock dictionary.
|
|
@end menu
|
|
|
|
None of the following sections apply to SBCL built without package
|
|
locking support.
|
|
|
|
The interface described here is experimental: incompatible changes
|
|
in future SBCL releases are possible, even expected: the concept of
|
|
@emph{implementation packages} and the associated operators may be
|
|
renamed; more operations (such as naming restarts or catch tags) may
|
|
be added to the list of operations violating package locks.
|
|
|
|
@node package lock concepts
|
|
@section Package Lock Concepts
|
|
|
|
@menu
|
|
* Implementation Packages: implementation packages.
|
|
* Package Lock Violations: package lock violations.
|
|
* Package Locks in Compiled Code: package locks in compiled code.
|
|
* Operations Violating Package Locks: operations violating package locks.
|
|
@end menu
|
|
|
|
Package locks protect against unintentional modifications of a package:
|
|
they provide similar protection to user packages as is mandated to
|
|
@code{common-lisp} package by the ANSI specification. They are not, and
|
|
should not be used as, a security measure.
|
|
|
|
Newly created packages are by default unlocked (see the @code{:lock} option
|
|
to @code{defpackage}).
|
|
|
|
The package @code{common-lisp} and SBCL internal implementation packages
|
|
are locked by default, including @code{sb-ext}.
|
|
|
|
It may be beneficial to lock @code{common-lisp-user} as well, to ensure
|
|
that various libraries don't pollute it without asking, but this is
|
|
not currently done by default.
|
|
|
|
@node implementation packages
|
|
@subsection Implementation Packages
|
|
|
|
Each package has a list of associated implementation packages. A
|
|
locked package, and the symbols whose home package it is, can be
|
|
modified without violating package locks only when @code{*package*} is
|
|
bound to one of the implementation packages of the locked package.
|
|
|
|
Unless explicitly altered by @code{defpackage},
|
|
@code{sb-ext:add-implementation-package}, or
|
|
@code{sb-ext:remove-implementation-package} each package is its own
|
|
(only) implementation package.
|
|
|
|
@node package lock violations
|
|
@subsection Package Lock Violations
|
|
|
|
@menu
|
|
* Lexical Bindings and Declarations: lexical bindings and declarations.
|
|
* Other Operations: other operations.
|
|
@end menu
|
|
|
|
@node lexical bindings and declarations
|
|
@subsubsection Lexical Bindings and Declarations
|
|
|
|
@cindex declaration
|
|
Lexical bindings or declarations that violate package locks cause a
|
|
compile-time warning, and a runtime @code{program-error} when the form that
|
|
violates package locks would be executed.
|
|
|
|
A complete listing of operators affect by this is: @code{let}, @code{let*}, @code{flet},
|
|
@code{labels}, @code{macrolet}, and @code{symbol-macrolet}, @code{declare}.
|
|
|
|
Package locks affecting both lexical bindings and declarations can
|
|
be disabled locally with the @code{sb-ext:disable-package-locks}
|
|
declaration, and re-enabled with the @code{sb-ext:enable-package-locks}
|
|
declaration.
|
|
|
|
Example:
|
|
|
|
@example
|
|
(in-package :locked)
|
|
|
|
(defun foo () ...)
|
|
|
|
(defmacro with-foo (&body body)
|
|
`(locally (declare (disable-package-locks locked:foo))
|
|
(flet ((foo () ...))
|
|
(declare (enable-package-locks locked:foo)) ; re-enable for body
|
|
,@@body)))
|
|
@end example
|
|
|
|
@node other operations
|
|
@subsubsection Other Operations
|
|
|
|
If an non-lexical operation violates a package lock, a continuable
|
|
error that is of a subtype of @code{sb-ext:package-lock-violation}
|
|
(subtype of @code{package-error}) is signalled when the operation is
|
|
attempted.
|
|
|
|
Additional restarts may be established for continuable package lock
|
|
violations for interactive use.
|
|
|
|
The actual type of the error depends on circumstances that caused
|
|
the violation: operations on packages signal errors of type
|
|
@code{sb-ext:package-locked-error}, and operations on symbols signal errors
|
|
of type @code{sb-ext:symbol-package-locked-error}.
|
|
|
|
@node package locks in compiled code
|
|
@subsection Package Locks in Compiled Code
|
|
|
|
If file-compiled code contains interned symbols, then loading that
|
|
code into an image without the said symbols will not cause a package
|
|
lock violation, even if the packages in question are locked.
|
|
|
|
With the exception of interned symbols, behaviour is unspecified if
|
|
package locks affecting compiled code are not the same during
|
|
loading of the code or execution.
|
|
|
|
Specifically, code compiled with packages unlocked may or may not
|
|
fail to signal package-lock-violations even if the packages are
|
|
locked at runtime, and code compiled with packages locked may or may
|
|
not signal spurious package-lock-violations at runtime even if the
|
|
packages are unlocked.
|
|
|
|
In practice all this means that package-locks have a negligible
|
|
performance penalty in compiled code as long as they are not
|
|
violated.
|
|
|
|
@node operations violating package locks
|
|
@subsection Operations Violating Package Locks
|
|
|
|
@menu
|
|
* Operations on Packages: operations on packages.
|
|
* Operations on Symbols: operations on symbols.
|
|
@end menu
|
|
|
|
@node operations on packages
|
|
@subsubsection Operations on Packages
|
|
|
|
The following actions cause a package lock violation if the package
|
|
operated on is locked, and @code{*package*} is not an implementation
|
|
package of that package, and the action would cause a change in the
|
|
state of the package (so e.g. exporting already external symbols is
|
|
never a violation). Package lock violations caused by these
|
|
operations signal errors of type @code{sb-ext:package-locked-error}.
|
|
|
|
@itemize
|
|
@item Shadowing a symbol in a package.
|
|
|
|
@item Importing a symbol to a package.
|
|
|
|
@item Uninterning a symbol from a package.
|
|
|
|
@item Exporting a symbol from a package.
|
|
|
|
@item Unexporting a symbol from a package.
|
|
|
|
@item Changing the packages used by a package.
|
|
|
|
@item Renaming a package.
|
|
|
|
@item Deleting a package.
|
|
|
|
@item Adding a new package local nickname to a package.
|
|
|
|
@item Removing an existing package local nickname to a package.
|
|
@end itemize
|
|
|
|
@node operations on symbols
|
|
@subsubsection Operations on Symbols
|
|
|
|
Following actions cause a package lock violation if the home package
|
|
of the symbol operated on is locked, and @code{*package*} is not an
|
|
implementation package of that package. Package lock violations
|
|
caused by these action signal errors of type
|
|
@code{sb-ext:symbol-package-locked-error}.
|
|
|
|
These actions cause only one package lock violation per lexically
|
|
apparent violated package.
|
|
|
|
Example:
|
|
|
|
|
|
@example
|
|
;;; Packages FOO and BAR are locked.
|
|
;;;
|
|
;;; Two lexically apparent violated packages: exactly two
|
|
;;; package-locked-errors will be signalled.
|
|
|
|
(defclass foo:point ()
|
|
((x :accessor bar:x)
|
|
(y :accessor bar:y)))
|
|
@end example
|
|
|
|
@itemize
|
|
@item Binding or altering its value lexically or dynamically, or
|
|
establishing it as a symbol-macro.
|
|
|
|
Exceptions:
|
|
|
|
@itemize
|
|
@item If the symbol is not defined as a constant, global
|
|
symbol-macro or a global dynamic variable, it may be lexically
|
|
bound or established as a local symbol macro.
|
|
|
|
@item If the symbol is defined as a global dynamic variable, it may
|
|
be assigned or bound.
|
|
@end itemize
|
|
|
|
@item Defining, undefining, or binding it, or its setf name as a
|
|
function.
|
|
|
|
Exceptions:
|
|
|
|
@itemize
|
|
@item If the symbol is not defined as a function, macro, or special
|
|
operator it and its setf name may be lexically bound as a
|
|
function.
|
|
@end itemize
|
|
|
|
@item Defining, undefining, or binding it as a macro or compiler macro.
|
|
|
|
Exceptions:
|
|
|
|
@itemize
|
|
@item If the symbol is not defined as a function, macro, or special
|
|
operator it may be lexically bound as a macro.
|
|
@end itemize
|
|
|
|
@item Defining it as a type specifier or structure.
|
|
|
|
@item Defining it as a declaration with a declaration proclamation.
|
|
|
|
@item Declaring or proclaiming it special.
|
|
|
|
@item Declaring or proclaiming its type or ftype.
|
|
|
|
Exceptions:
|
|
|
|
@itemize
|
|
@item If the symbol may be lexically bound, the type of that binding
|
|
may be declared.
|
|
|
|
@item If the symbol may be lexically bound as a function, the ftype
|
|
of that binding may be declared.
|
|
@end itemize
|
|
|
|
@item Defining a setf expander for it.
|
|
|
|
@item Defining it as a method combination type.
|
|
|
|
@item Using it as the @code{class-name} argument to (@code{setf} @code{find-class}).
|
|
|
|
@item Defining it as a hash table test using @code{sb-ext:define-hash-table-test}.
|
|
@end itemize
|
|
|
|
@node package lock dictionary
|
|
@section Package Lock Dictionary
|
|
|
|
@anchor{Declaration sb-ext disable-package-locks}
|
|
@ddindex @sortas{disable-package-locks sb-ext} disable-package-locks [sb-ext]
|
|
@deffn{Declaration} sb-ext:disable-package-locks
|
|
Syntax: @code{(sb-ext:disable-package-locks &rest symbols)}
|
|
|
|
Disables package locks affecting the named symbols during compilation
|
|
in the lexical scope of the declaration. Disabling locks on symbols
|
|
whose home package is unlocked, or disabling an already disabled lock,
|
|
has no effect.
|
|
@end deffn
|
|
@anchor{Declaration sb-ext enable-package-locks}
|
|
@ddindex @sortas{enable-package-locks sb-ext} enable-package-locks [sb-ext]
|
|
@deffn{Declaration} sb-ext:enable-package-locks
|
|
Syntax: @code{(sb-ext:enable-package-locks &rest symbols)}
|
|
|
|
Re-enables package locks affecting the named symbols during
|
|
compilation in the lexical scope of the declaration. Enabling locks
|
|
that were not first disabled with @code{sb-ext:disable-package-locks}
|
|
declaration, or enabling locks that are already enabled has no effect.
|
|
@end deffn
|
|
@anchor{Condition sb-ext package-lock-violation}
|
|
@ttindex @sortas{package-lock-violation sb-ext} package-lock-violation [sb-ext]
|
|
@deffn{Condition} sb-ext:package-lock-violation
|
|
Subtype of @code{cl:package-error}. A subtype of this error is signalled
|
|
when a package-lock is violated.
|
|
@end deffn
|
|
@anchor{Condition sb-ext package-locked-error}
|
|
@ttindex @sortas{package-locked-error sb-ext} package-locked-error [sb-ext]
|
|
@deffn{Condition} sb-ext:package-locked-error
|
|
Subtype of @code{sb-ext:package-lock-violation}. An error of this type is
|
|
signalled when an operation on a package violates a package lock.
|
|
@end deffn
|
|
@anchor{Condition sb-ext symbol-package-locked-error}
|
|
@ttindex @sortas{symbol-package-locked-error sb-ext} symbol-package-locked-error [sb-ext]
|
|
@deffn{Condition} sb-ext:symbol-package-locked-error
|
|
Subtype of @code{sb-ext:package-lock-violation}. An error of this type is
|
|
signalled when an operation on a symbol violates a package lock. The
|
|
symbol that caused the violation is accessed by the function
|
|
@code{sb-ext:package-locked-error-symbol}.
|
|
@end deffn
|
|
@anchor{Function sb-ext package-locked-error-symbol}
|
|
@ffindex @sortas{package-locked-error-symbol sb-ext} package-locked-error-symbol [sb-ext]
|
|
@deffn{Function} sb-ext:package-locked-error-symbol condition
|
|
Return the symbol that caused the @code{symbol-package-locked-error}
|
|
condition.
|
|
@end deffn
|
|
@anchor{Function sb-ext package-locked-p}
|
|
@ffindex @sortas{package-locked-p sb-ext} package-locked-p [sb-ext]
|
|
@deffn{Function} sb-ext:package-locked-p package
|
|
Returns @code{t} when @code{package} is locked, @code{nil} otherwise. Signals an error
|
|
if @code{package} doesn't designate a valid package.
|
|
@end deffn
|
|
@anchor{Function sb-ext lock-package}
|
|
@ffindex @sortas{lock-package sb-ext} lock-package [sb-ext]
|
|
@deffn{Function} sb-ext:lock-package package
|
|
Locks @code{package} and returns @code{t}. Has no effect if @code{package} was already
|
|
locked. Signals an error if @code{package} is not a valid package designator
|
|
@end deffn
|
|
@anchor{Function sb-ext unlock-package}
|
|
@ffindex @sortas{unlock-package sb-ext} unlock-package [sb-ext]
|
|
@deffn{Function} sb-ext:unlock-package package
|
|
Unlocks @code{package} and returns @code{t}. Has no effect if @code{package} was already
|
|
unlocked. Signals an error if @code{package} is not a valid package designator.
|
|
@end deffn
|
|
@anchor{Function sb-ext package-implemented-by-list}
|
|
@ffindex @sortas{package-implemented-by-list sb-ext} package-implemented-by-list [sb-ext]
|
|
@deffn{Function} sb-ext:package-implemented-by-list package
|
|
Returns a list containing the implementation packages of
|
|
@code{package}. Signals an error if @code{package} is not a valid package designator.
|
|
@end deffn
|
|
@anchor{Function sb-ext package-implements-list}
|
|
@ffindex @sortas{package-implements-list sb-ext} package-implements-list [sb-ext]
|
|
@deffn{Function} sb-ext:package-implements-list package
|
|
Returns the packages that @code{package} is an implementation package
|
|
of. Signals an error if @code{package} is not a valid package designator.
|
|
@end deffn
|
|
@anchor{Function sb-ext add-implementation-package}
|
|
@ffindex @sortas{add-implementation-package sb-ext} add-implementation-package [sb-ext]
|
|
@deffn{Function} sb-ext:add-implementation-package packages-to-add &optional package
|
|
Adds @code{packages-to-add} as implementation packages of @code{package}. Signals
|
|
an error if @code{package} or any of the @code{packages-to-add} is not a valid
|
|
package designator.
|
|
@end deffn
|
|
@anchor{Function sb-ext remove-implementation-package}
|
|
@ffindex @sortas{remove-implementation-package sb-ext} remove-implementation-package [sb-ext]
|
|
@deffn{Function} sb-ext:remove-implementation-package packages-to-remove &optional package
|
|
Removes @code{packages-to-remove} from the implementation packages of
|
|
@code{package}. Signals an error if @code{package} or any of the @code{packages-to-remove}
|
|
is not a valid package designator.
|
|
@end deffn
|
|
@anchor{Macro sb-ext without-package-locks}
|
|
@ffindex @sortas{without-package-locks sb-ext} without-package-locks [sb-ext]
|
|
@deffn{Macro} sb-ext:without-package-locks &body body
|
|
Ignores all runtime package lock violations during the execution of
|
|
body. Body can begin with declarations.
|
|
@end deffn
|
|
@anchor{Macro sb-ext with-unlocked-packages}
|
|
@ffindex @sortas{with-unlocked-packages sb-ext} with-unlocked-packages [sb-ext]
|
|
@deffn{Macro} sb-ext:with-unlocked-packages (&rest packages) &body forms
|
|
Unlocks @code{packages} for the dynamic scope of the body. Signals an
|
|
error if any of @code{packages} is not a valid package designator.
|
|
@end deffn
|
|
The @code{defpackage} options are extended to include the following:
|
|
|
|
@itemize
|
|
@item @code{:lock} @code{<boolean>} (defaults to @code{nil})
|
|
|
|
If the argument to @code{:lock} is @code{t}, the package is locked, else it is
|
|
unlocked. Existing package are also affected.
|
|
|
|
@item @code{:implement} @code{<package-designator>*}
|
|
|
|
The package is added as an implementation package to the
|
|
packages named. If @code{:implement} is not provided, it defaults to
|
|
the package itself.
|
|
@end itemize
|
|
|
|
Example:
|
|
|
|
@example
|
|
(defpackage "FOO" (:export "BAR") (:lock t) (:implement))
|
|
(defpackage "FOO-INT" (:use "FOO") (:implement "FOO" "FOO-INT"))
|
|
|
|
;;; is equivalent to
|
|
|
|
(defpackage "FOO") (:export "BAR"))
|
|
(lock-package "FOO")
|
|
(remove-implementation-package "FOO" "FOO")
|
|
|
|
(defpackage "FOO-INT" (:use "BAR"))
|
|
(add-implementation-package "FOO-INT" "FOO")
|
|
@end example
|
|
|