- don't assume that any keyword is an option
- don't process the same keyword twice
New behavior could be summarized in these two cases:
(restart-case t
(retry ()
:retired ; <- form
))
(restart-case t
(retry ()
:report report ; <- expression
:report "foo" ; <- form
:test test ; <- form
))
Fixes#666.
Previously c1make-var checked whether the symbol NAME is CONSTANTP, but
ECL expands symbol macros in CONSTANTP so this returned false positives.
A similar concern applied to the CMP-ENV-REGISTER-SYMBOL-MACRO-FUNCTION.
C1EXPR-INNER when encountered a symbol tried to yield C1CONSTANT-VALUE
for if it iwas CONSTANTP - this was correct except for that we didn't
pass the environment to the predicate and symbols weren't shadowed.
In this commit one function is added to the core - si:constp (with
similar purpose to si:specialp) and one function to the compiler -
constant-variable-p (similar to special-variable-p) and they are
appropriately used when necessary. A regression test is added.
Fixes#662.
Read-write locks are always provided; if no operating system
primitives exist, emulate them using ordinary locks. Also provide a
Windows implementation.
- Spinlocks have been replaced by ordinary locks. Without access to
the underyling scheduler, spinlocks provide no performace benefit
and may even be harmful in case of high contention.
- Synchronization of process creation and exiting has been simplified.
Instead of a spinlock, a barrier and atomic operations we now use
only a single lock protecting the shared process state and a
condition variable for implementing process joins.
- Some locks which were implemented using Lisp objects now directly
use a native mutex.
- Our own mutex implementation has been removed as it is now unused.
The old implementation was not race condition free. If two threads (A
and B) were writing at the same time while one thread (C) was reading,
the following could happen:
1. thread A increases the write pointer (but does not store the
message yet)
2. thread B increases the write pointer, stores the message and
signals thread C
3. thread C tries to read from the location that thread A has not yet
written to
The new implementation is a simple and obvious solution using a common
mutex and two condition variables for reading/writing. We don't bother
with a (complex) interrupt safe implementation.
We already have a race condition between mp:get-lock and
mp:holding-lock-p, there is no point in trying to make sure the lock
is released at all costs during an interrupt.
Changes include:
- consistent naming
- replaced unnecessary use of (sleep) by better synchronization mechanisms
- tests are run with timeouts
- clean up stray threads which would otherwise wait for all eternity
- better error messages in case of test failures
Replace slow homegrown mutex implementation by standard OS functions.
We try our best to be interrupt safe, however a completely safe
implementation is impossible (unless one completely removes the ability
to interrupt a thread waiting on a mutex). There is always a window
after the OS specific function has returned, but before we can set
the owner, in which interrupts will see an inconsistent state of the
mutex with regards to owner and count.
Condition variables are now based on OS functions as well. Timed
waiting on condition variables has also been implemented.
On Unix, pathnames are converted into the default encoding specified
by ext:*default-external-format* and back. On Windows, the operating
system already gives us utf16 encoded pathnames, so we use those.
ecl_namestring with ECL_NAMESTRING_FORCE_BASE_STRING encodes with the
specified encoding. Decoding is handled individually in the filesystem
functions.
Includes a minor refactor of list_directory, changing the
PARSE_DIRECTORY_ENTRY macro into an inline function.
Closes#609, #549.
This commit complements the previous one by ensuring that concatenated files are
read in order (after processing previous files) and that we don't check whether
packages are created before we process all files.
This function can be found in lisp code (it is generated by the reader
from backquotes), thus it must be declared in external.h so that the C
compiler can pick it up when we compile the generated C file.
Fixes#648.