mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-24 21:41:29 -08:00
add package-locks abstraction
We follow the protocol proposed by SBCL.
This commit is contained in:
parent
861b286f40
commit
36b1b1d3cc
5 changed files with 103 additions and 13 deletions
|
|
@ -116,7 +116,10 @@ ecl_rem_setf_definition(cl_object sym)
|
|||
if (Null(cl_functionp(def)))
|
||||
FEinvalid_function(def);
|
||||
pack = ecl_symbol_package(sym);
|
||||
if (pack != ECL_NIL && pack->pack.locked) {
|
||||
if (pack != ECL_NIL
|
||||
&& pack->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL) {
|
||||
CEpackage_error("Attempt to redefine function ~S in locked package.",
|
||||
"Ignore lock and proceed", pack, 1, fname);
|
||||
}
|
||||
|
|
@ -167,7 +170,10 @@ cl_fmakunbound(cl_object fname)
|
|||
{
|
||||
cl_object sym = si_function_block_name(fname);
|
||||
cl_object pack = ecl_symbol_package(sym);
|
||||
if (pack != ECL_NIL && pack->pack.locked) {
|
||||
if (pack != ECL_NIL
|
||||
&& pack->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL) {
|
||||
CEpackage_error("Attempt to redefine function ~S in locked package.",
|
||||
"Ignore lock and proceed", pack, 1, fname);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,9 @@ ecl_rename_package(cl_object x, cl_object name, cl_object nicknames)
|
|||
name = cl_string(name);
|
||||
nicknames = process_nicknames(nicknames);
|
||||
x = si_coerce_to_package(x);
|
||||
if (x->pack.locked) {
|
||||
if (x->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL) {
|
||||
CEpackage_error("Cannot rename locked package ~S.",
|
||||
"Ignore lock and proceed", x, 0);
|
||||
}
|
||||
|
|
@ -369,7 +371,10 @@ ecl_intern(cl_object name, cl_object p, int *intern_flag)
|
|||
s = find_symbol_inner(name, p, intern_flag);
|
||||
if (*intern_flag) {
|
||||
error = 0;
|
||||
} else if (p->pack.locked && !ignore_error) {
|
||||
} else if (p->pack.locked
|
||||
&& !ignore_error
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL) {
|
||||
error = 1;
|
||||
} else {
|
||||
s = cl_make_symbol(name);
|
||||
|
|
@ -472,7 +477,9 @@ ecl_unintern(cl_object s, cl_object p)
|
|||
cl_object name = ecl_symbol_name(s);
|
||||
|
||||
p = si_coerce_to_package(p);
|
||||
if (p->pack.locked) {
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL) {
|
||||
CEpackage_error("Cannot unintern symbol ~S from locked package ~S.",
|
||||
"Ignore lock and proceed", p, 2, s, p);
|
||||
}
|
||||
|
|
@ -531,7 +538,9 @@ cl_export2(cl_object s, cl_object p)
|
|||
int intern_flag, error;
|
||||
cl_object other_p, name = ecl_symbol_name(s);
|
||||
p = si_coerce_to_package(p);
|
||||
if (p->pack.locked)
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL)
|
||||
CEpackage_error("Cannot export symbol ~S from locked package ~S.",
|
||||
"Ignore lock and proceed", p, 2, s, p);
|
||||
AGAIN:
|
||||
|
|
@ -584,7 +593,9 @@ cl_delete_package(cl_object p)
|
|||
"Ignore error and continue", p, 0);
|
||||
@(return ECL_NIL);
|
||||
}
|
||||
if (p->pack.locked)
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL)
|
||||
CEpackage_error("Cannot delete locked package ~S.",
|
||||
"Ignore lock and proceed", p, 0);
|
||||
if (p == cl_core.lisp_package || p == cl_core.keyword_package) {
|
||||
|
|
@ -635,7 +646,9 @@ cl_unexport2(cl_object s, cl_object p)
|
|||
FEpackage_error("Cannot unexport a symbol from the keyword package.",
|
||||
cl_core.keyword_package, 0);
|
||||
}
|
||||
if (p->pack.locked) {
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL) {
|
||||
CEpackage_error("Cannot unexport symbol ~S from locked package ~S.",
|
||||
"Ignore lock and proceed", p, 2, s, p);
|
||||
}
|
||||
|
|
@ -667,7 +680,9 @@ cl_import2(cl_object s, cl_object p)
|
|||
int intern_flag, error, ignore_error = 0;
|
||||
cl_object name = ecl_symbol_name(s);
|
||||
p = si_coerce_to_package(p);
|
||||
if (p->pack.locked) {
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL) {
|
||||
CEpackage_error("Cannot import symbol ~S into locked package ~S.",
|
||||
"Ignore lock and proceed", p, 2, s, p);
|
||||
}
|
||||
|
|
@ -706,7 +721,9 @@ ecl_shadowing_import(cl_object s, cl_object p)
|
|||
cl_object x;
|
||||
cl_object name = ecl_symbol_name(s);
|
||||
p = si_coerce_to_package(p);
|
||||
if (p->pack.locked)
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL)
|
||||
CEpackage_error("Cannot shadowing-import symbol ~S into "
|
||||
"locked package ~S.",
|
||||
"Ignore lock and proceed", p, 2, s, p);
|
||||
|
|
@ -745,7 +762,9 @@ ecl_shadow(cl_object s, cl_object p)
|
|||
/* Contrary to CLTL, in ANSI CL, SHADOW operates on strings. */
|
||||
s = cl_string(s);
|
||||
p = si_coerce_to_package(p);
|
||||
if (p->pack.locked)
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL)
|
||||
CEpackage_error("Cannot shadow symbol ~S in locked package ~S.",
|
||||
"Ignore lock and proceed", p, 2, s, p);
|
||||
ECL_WITH_GLOBAL_ENV_WRLOCK_BEGIN(ecl_process_env()) {
|
||||
|
|
@ -779,7 +798,9 @@ ecl_use_package(cl_object x, cl_object p)
|
|||
if (p == cl_core.keyword_package)
|
||||
FEpackage_error("Cannot apply USE-PACKAGE on keyword package.",
|
||||
cl_core.keyword_package, 0);
|
||||
if (p->pack.locked)
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL)
|
||||
CEpackage_error("Cannot use package ~S in locked package ~S.",
|
||||
"Ignore lock and proceed",
|
||||
p, 2, x, p);
|
||||
|
|
@ -817,7 +838,9 @@ ecl_unuse_package(cl_object x, cl_object p)
|
|||
{
|
||||
x = si_coerce_to_package(x);
|
||||
p = si_coerce_to_package(p);
|
||||
if (p->pack.locked)
|
||||
if (p->pack.locked
|
||||
&& ECL_SYM_VAL(ecl_process_env(),
|
||||
@'si::*ignore-package-locks*') == ECL_NIL)
|
||||
CEpackage_error("Cannot unuse package ~S from locked package ~S.",
|
||||
"Ignore lock and proceed",
|
||||
p, 2, x, p);
|
||||
|
|
|
|||
|
|
@ -1207,7 +1207,15 @@ cl_symbols[] = {
|
|||
{EXT_ "MKSTEMP", EXT_ORDINARY, si_mkstemp, 1, OBJNULL},
|
||||
{SYS_ "RMDIR", SI_ORDINARY, si_rmdir, 1, OBJNULL},
|
||||
{EXT_ "MAKE-PIPE", EXT_ORDINARY, si_make_pipe, 0, OBJNULL},
|
||||
/* PACKAGE_LOCKS */
|
||||
{SYS_ "*IGNORE-PACKAGE-LOCKS*", SI_SPECIAL, NULL, -1, ECL_NIL},
|
||||
{EXT_ "PACKAGE-LOCK", EXT_ORDINARY, si_package_lock, 2, OBJNULL},
|
||||
{SYS_ "LOCK-PACKAGE", EXT_ORDINARY, NULL, 1, OBJNULL},
|
||||
{SYS_ "UNLOCK-PACKAGE", EXT_ORDINARY, NULL, 1, OBJNULL},
|
||||
{SYS_ "PACKAGE-LOCKED-P", EXT_ORDINARY, NULL, 1, OBJNULL},
|
||||
{SYS_ "WITHOUT-PACKAGE-LOCKS", EXT_ORDINARY, NULL, 1, OBJNULL},
|
||||
{SYS_ "WITH-UNLOCKED-PACKAGES", EXT_ORDINARY, NULL, 1, OBJNULL},
|
||||
/* ~PACKAGE_LOCKS */
|
||||
{SYS_ "PACKAGE-HASH-TABLES", SI_ORDINARY, si_package_hash_tables, 1, OBJNULL},
|
||||
{SYS_ "PATHNAME-TRANSLATIONS", SI_ORDINARY, si_pathname_translations, -1, OBJNULL},
|
||||
{SYS_ "POINTER", SI_ORDINARY, si_pointer, 1, OBJNULL},
|
||||
|
|
|
|||
|
|
@ -1207,7 +1207,15 @@ cl_symbols[] = {
|
|||
{EXT_ "MKSTEMP","si_mkstemp"},
|
||||
{SYS_ "RMDIR","si_rmdir"},
|
||||
{EXT_ "MAKE-PIPE","si_make_pipe"},
|
||||
/* PACKAGE_LOCKS */
|
||||
{SYS_ "*IGNORE-PACKAGE-LOCKS*",NULL},
|
||||
{EXT_ "PACKAGE-LOCK","si_package_lock"},
|
||||
{SYS_ "LOCK-PACKAGE",NULL},
|
||||
{SYS_ "UNLOCK-PACKAGE",NULL},
|
||||
{SYS_ "PACKAGE-LOCKED-P",NULL},
|
||||
{SYS_ "WITHOUT-PACKAGE-LOCKS",NULL},
|
||||
{SYS_ "WITH-UNLOCKED-PACKAGES",NULL},
|
||||
/* ~PACKAGE_LOCKS */
|
||||
{SYS_ "PACKAGE-HASH-TABLES","si_package_hash_tables"},
|
||||
{SYS_ "PATHNAME-TRANSLATIONS","si_pathname_translations"},
|
||||
{SYS_ "POINTER","si_pointer"},
|
||||
|
|
|
|||
|
|
@ -284,3 +284,48 @@ If PACKAGE is non-NIL, then only the specified PACKAGE is searched."
|
|||
(prefix (string-prefix-p parent-prefix package-name)))
|
||||
(when (and prefix (or recurse (not (find #\. package-name :start prefix))))
|
||||
(pushnew package res)))))))
|
||||
|
||||
|
||||
;;; Package locks
|
||||
(pushnew :package-locks *features*)
|
||||
|
||||
(defun lock-package (package &aux (package (si:coerce-to-package package)))
|
||||
(ffi:c-inline (package) (:object) :void
|
||||
"(#0)->pack.locked = 1"
|
||||
:side-effects t
|
||||
:one-liner t))
|
||||
|
||||
(defun unlock-package (package &aux (package (si:coerce-to-package package)))
|
||||
(ffi:c-inline (package) (:object) :void
|
||||
"(#0)->pack.locked = 0"
|
||||
:side-effects t
|
||||
:one-liner t))
|
||||
|
||||
(defun package-locked-p (package &aux (package (si:coerce-to-package package)))
|
||||
"Returns T when PACKAGE is locked, NIL otherwise. Signals an error
|
||||
if PACKAGE doesn't designate a valid package."
|
||||
(ffi:c-inline (package) (:object) :object
|
||||
"(#0)->pack.locked ? ECL_T : ECL_NIL"
|
||||
:side-effects nil
|
||||
:one-liner t))
|
||||
|
||||
(defmacro without-package-locks (&body body)
|
||||
"Ignores all runtime package lock violations during the execution of
|
||||
body. Body can begin with declarations."
|
||||
`(let ((si::*ignore-package-locks* t)) ,@body))
|
||||
|
||||
(defmacro with-unlocked-packages ((&rest packages) &body forms)
|
||||
"Unlocks PACKAGES for the dynamic scope of the body. Signals an
|
||||
error if any of PACKAGES is not a valid package designator."
|
||||
(with-unique-names (unlocked-packages)
|
||||
`(let (,unlocked-packages)
|
||||
(unwind-protect
|
||||
(progn
|
||||
(dolist (p ',packages)
|
||||
(when (package-locked-p p)
|
||||
(push p ,unlocked-packages)
|
||||
(unlock-package p)))
|
||||
,@forms)
|
||||
(dolist (p ,unlocked-packages)
|
||||
(when (find-package p)
|
||||
(lock-package p)))))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue