@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 affected by this is: @code{let}, @code{let*},
@code{flet}, @code{labels}, @code{macrolet}, @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 a 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 from 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

