2009/4/26 Daniel Herring <dherring@...>:
This is veering pretty far off track, but...
> People might think it is safe to use defvar to initialize shared resources
> as part of thread initialization.
>
> e.g.
> (defvar *space* (allocate-1GB-or-die))
> (defvar *port* (open-serial-port-or-die))
...I would certainly hope that people don't routinely run toplevel
code like that as part of thread initialization!
> Since (IIRC) special variables are stored thread-local, this looks like a
> good way to define global (static, shared) storage.
Non-global special variable bindings are thread-local, yes: if you
rebind a special in a thread using LET, PROGV, or whatever, that
binding is thread local.
Cheers,
-- Nikodemus

On Sun, 26 Apr 2009, Nikodemus Siivola wrote:
> 2009/4/26 Faré <fahree@...>:
>
>> Following this line of reasoning, even DEFVAR would be bad
>> unless DEFVAR itself is atomic between the moment it checks for boundp
>> and the moment it commits the new value.
>
> Um. I find that a fairly extreme position. I think it's reasonable to
> assume that you may during development be reloading code that happens
> to have things like
>
> (defvar *lock* (make-mutex))
>
> in it while threads holding those locks are running, in which case
> DEFVAR does TRT -- keeps the old lock in place instead of nuking it.
I think Fare's point still holds for actions which have costly side
effects. People might think it is safe to use defvar to initialize shared
resources as part of thread initialization.
e.g.
(defvar *space* (allocate-1GB-or-die))
(defvar *port* (open-serial-port-or-die))
That said, the standard procedure in other languages is to initialize such
shared structures before spawning new threads (or telling existing threads
to use them) or use explicit synchronization (e.g. a mutex or
pthread_once) to coordinate their initialization at runtime. So I see no
need to use a mutex or atomic op in DEFGLOBAL just as long as the
documentation is clear.
Since (IIRC) special variables are stored thread-local, this looks like a
good way to define global (static, shared) storage.
- Daniel

2009/4/26 Lars Rune Nøstdal <larsnostdal@...>:
> Interesting. Reminds me of:
> http://www.nhplace.com/kent/CL/Issues/proclaim-lexical.html
>
> ..but simpler.
>
> If I got this right, depenending on how one look at it, DEFGLOBAL is
> basically a DEFVAR with some constraints added (safety for users or
> clarity of intent) and/or features removed (faster?).
Yes, about so. The DEFLEX macro in the other email implements the
semantics of the lexical variables proposed in the issue: first
lexical, then global lookup.
> I have at least one place in my code where I can see both of these
> effects being useful.
Good to hear!
Cheers,
-- Nikodemus

On Sat, 2009-04-25 at 19:11 +0300, Nikodemus Siivola wrote:
> The attached patch is a work-in-progress, providing declarations
> GLOBAL and ALWAYS-BOUND, and uses these to implement DEFGLOBAL.
>
> GLOBAL declaration is analogous to SPECIAL: global variables cannot be
> locally bound or defined/bound as symbol macros, and all threads share
> the same value. The intention behind prohibiting rebinding is that
> this seems like a useful property that cannot be implemented by users:
> those wanting globals that _can_ be rebound can simply wrap the global
> in a symbol-macro to get the rebinding-allowing semantics. The
> intention is to support it as a local declaration as well, but this
> has not been implemented yet.
>
> ALWAYS-BOUND declaration is a bit more special: it can only be used in
> DECLAIM/PROCLAIM, not in a local DECLARE. To proclaim a variable as
> ALWAYS-BOUND it needs to be already bound and not a constant. The
> proclamation inhibits future attempts to MAKUNBOUND it. The reason for
> prohibiting local ALWAYS-BOUND declarations is that they are not safe
> -- and (OPTIMIZE (SAFETY 0)) already has the same effect in practice.
> If this is deemed too ugly, I can add support for local declarations
> as well -- either as no-ops, or as no-ops outside safe code, or
> whatever.
>
> DEFGLOBAL proclaims the defined variable as both GLOBAL and
> ALWAYS-BOUND, and is sort of between DEFVAR and DEFCONSTANT: the value
> is evaluated both compile-time and load-time iff the name is not
> already bound, in order to allow for the ALWAYS-BOUND declaration.
> This is to make things like
>
> (defglobal .lock. (make-mutex))
>
> safe (so as not to replace the mutex with a new one when
> reloading/compiling a file, etc), and to make DEFGLOBAL a mostly
> drop-in replacement for DEFVAR and DEFCONSTANT where appropriate.
> Users needing global equivalents of DEFPARAMETER get to roll their
> own.
>
> How does this look?
Interesting. Reminds me of:
http://www.nhplace.com/kent/CL/Issues/proclaim-lexical.html
..but simpler.
If I got this right, depenending on how one look at it, DEFGLOBAL is
basically a DEFVAR with some constraints added (safety for users or
clarity of intent) and/or features removed (faster?).
I have at least one place in my code where I can see both of these
effects being useful.
> Cheers,
>
> -- Nikodemus

2009/4/26 Faré <fahree@...>:
> Following this line of reasoning, even DEFVAR would be bad
> unless DEFVAR itself is atomic between the moment it checks for boundp
> and the moment it commits the new value.
Um. I find that a fairly extreme position. I think it's reasonable to
assume that you may during development be reloading code that happens
to have things like
(defvar *lock* (make-mutex))
in it while threads holding those locks are running, in which case
DEFVAR does TRT -- keeps the old lock in place instead of nuking it.
While DEFVAR without a global lock is certainly racy when it comes to
boundness checking, I think it's clear that encountering the boundness
race in the real world is infinitely rarer than the case outlined
above: it requires you to load code in parallel instead of just
developing while your application is running.
*** At any rate the core point is that DEFGLOBAL is analogous to
DEFVAR in the sense that is does not evaluate if the variable is
already bound, making it a drop-in replacement for it when rebinding
is not needed. ***
> But then again, I don't understand defglobal in the context of this
> remark. Will DEFGLOBAL prevent re-binding just like DEFCONSTANT? Then
> what does it do that DEFCONSTANT doesn't? Or if it does allow
> re-binding, isn't it just as bad as DEFPARAMETER in the context of
> your remark? Or will it only allow re-binding with SETF, and treat any
> subsequent DEFGLOBAL as either an error or a nop? I'm confused.
There is terminology confusion here: when I say "rebinding" I mean
LET, PROGV, LAMBDA, etc.
DEFGLOBAL prevents rebinding like DEFCONSTANT. It also prohibits
MAKUNBOUND. Re-evaluating a it is a nop. SETF is allowed.
Cheers,
-- Nikodemus

2009/4/26 Nikodemus Siivola <nikodemus@...>:
> 2009/4/26 Leslie P. Polzer <sky@...>:
>>> (defglobal .lock. (make-mutex))
>>> safe (so as not to replace the mutex with a new one when
>>> reloading/compiling a file, etc),
>> I don't get this: what would the behavior of DEFVAR be instead?
> DEFVAR would be fine there as well -- but DEFPARAMETER would not.
> DEFVAR evaluates the value form at load time iff the variable is
> unbound at that point, so you'd never risk getting two locks (with
> potentially running code already holding on to the other.)
Following this line of reasoning, even DEFVAR would be bad
unless DEFVAR itself is atomic between the moment it checks for boundp
and the moment it commits the new value.
But then again, I don't understand defglobal in the context of this
remark. Will DEFGLOBAL prevent re-binding just like DEFCONSTANT? Then
what does it do that DEFCONSTANT doesn't? Or if it does allow
re-binding, isn't it just as bad as DEFPARAMETER in the context of
your remark? Or will it only allow re-binding with SETF, and treat any
subsequent DEFGLOBAL as either an error or a nop? I'm confused.
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
Both politicians and journalists face situations which strain their honesty
and humanity. My opinion is that politicians on the average stand up somewhat
better than journalists. -- John McCarthy

2009/4/26 Leslie P. Polzer <sky@...>:
>
>> (defglobal .lock. (make-mutex))
>>
>> safe (so as not to replace the mutex with a new one when
>> reloading/compiling a file, etc),
>
> I don't get this: what would the behavior of DEFVAR be instead?
DEFVAR would be fine there as well -- but DEFPARAMETER would not.
DEFVAR evaluates the value form at load time iff the variable is
unbound at that point, so you'd never risk getting two locks (with
potentially running code already holding on to the other.)
DEFPARAMETER would be Bad There.
Point was that DEFGLOBAL is like DEFVAR in the sense that it does not
re-evaluate if the variable is bound: if the variable is never bound
it can be used as a drop-in replacement.
Apropos, I originally neglected to mention that I consider this stuff
primarily an efficiency measure: special variable access is relatively
slow on threaded builds due to need to check for thread-local
bindings. If rebinding is not needed, using DEFGLOBAL not only
expresses the intention better, but removes the TLS overhead. Quick
benchmarking shows that global accesses are up to 50% faster than
special variable accesses.
Cheers,
-- Nikodemus

2009/4/26 Tobias C. Rittweiler <tcr@...>:
>> ...and note the wierdness of CONS and non-simple ARRAY types in the
>> manual, of course...
> Section? (I looked through 3.2 but couldn't find it.)
Yeah. 33.2 is where I would put it -- haven't written it yet.
> That's a nice poor man's algebraic-datatype like feature.
...
> Is that a good enough use case to see incentive to extend your work to
> make it probably derive types in DESTRUCTURING-BIND? :-)
Unfortunately not in the short term at least: it would be nice to
have, but looks like far more work for relatively marginal gains.
Compiler bugs with potential for heap corruption (and wrong answers)
are one thing, better type derivation for relatively marginal cases
another.
Cheers,
-- Nikodemus

Nikodemus Siivola <nikodemus@...> writes:
> 2009/4/25 Tobias C. Rittweiler <...>:
>
> > The patch does not guard against [violating DECLARE type declarations]
>
> Inserting casts for things like that would be possible, but not in the
> general case: replace the (SETF CAR) with a call to FOO that does the
> same, and the compiler has no way to guard against it. (Ok, I suppose
> we could check the type again after any unknown call, but that would
> suck pretty badly -- not to mention that type TYPE-ERROR would arise
> after the damage has been done, which would be pretty wierd.
>
> The only thing that I can think of that could be done would be to
> never trust a specific CONS type or the dimensions of a non-simple
> ARRAY is safe code -- even if it is declared. Hm, yes, that might be a
> good idea.
Yes, or only trust it if you can be sure it's not going to be
violated. (E.g. the variable is only passed to accessors functions,
later perhaps to any function that is declared to be
flushable---although I don't know how accurate the information is in
fndb.)
Bonus point if you can make it emit a note saying "forced to downgrade
from more specific type (CONS FIXNUM (CONS FIXNUM NULL)) to LIST." on
appropriate optimization settings.
> ...and note the wierdness of CONS and non-simple ARRAY types in the
> manual, of course...
Section? (I looked through 3.2 but couldn't find it.)
It would be useful if the manual was not only available
one-site-per-node, but also everything-in-one-page.
> > [DESTRUCTURING-BIND on return value declared to be (CONS FIXNUM ...)]
> >
> > For me that's the most obvious use case for specifying compound list
> > types.
>
> I believe the most common case is when you need to store pairs of
> fixnums and want to save one word as opposed to using (COMPLEX
> FIXNUM).
>
> I'll probably merge this patch as 1.0.28.early, and people who use
> (CONS FIXNUM) can then test it to see if they get performance
> regressions in their applications.
I've got a DEFTRANSFORM on PROPER-LENGTH-OF-LENGTH so DESTRUCTURING-BIND
will complain at compile-time if the lambda-list does contain too many,
or does not contain enough required parameters.
E.g.
(destructuring-bind (x y) (compute-fixed-list ...)
...)
with the COMPUTE-FIXED-LIST of my previous message would result in a
code deletion note.
Furthermore, I modified DEFSTRUCT to use compound CONS specifiers for
(defstruct (foo (:type list))
(a :type fixnum)
(b :type fixnum)
(b :type fixnum))
Now if you later add a new slot, or remove one, *all* the
DESTRUCTURING-BINDs in my code will emit notes, and I can easily fix
them appropriately.
That's a nice poor man's algebraic-datatype like feature.
Is that a good enough use case to see incentive to extend your work to
make it probably derive types in DESTRUCTURING-BIND? :-)
-T.

2009/4/25 Matthew D. Swank <akopa@...>:
> However, I wanted to know what should the correct behavior of
> run-program be?
If I understand you question correctly, yes, it should always either
return a PROCESS object or signal an error. From the docstring (note
the amusing historical artifact...):
RUN-PROGRAM will return a PROCESS structure. See the CMU Common Lisp
Users Manual for details about the PROCESS structure.
Cheers,
-- Nikodemus

The attached patch is a work-in-progress, providing declarations
GLOBAL and ALWAYS-BOUND, and uses these to implement DEFGLOBAL.
GLOBAL declaration is analogous to SPECIAL: global variables cannot be
locally bound or defined/bound as symbol macros, and all threads share
the same value. The intention behind prohibiting rebinding is that
this seems like a useful property that cannot be implemented by users:
those wanting globals that _can_ be rebound can simply wrap the global
in a symbol-macro to get the rebinding-allowing semantics. The
intention is to support it as a local declaration as well, but this
has not been implemented yet.
ALWAYS-BOUND declaration is a bit more special: it can only be used in
DECLAIM/PROCLAIM, not in a local DECLARE. To proclaim a variable as
ALWAYS-BOUND it needs to be already bound and not a constant. The
proclamation inhibits future attempts to MAKUNBOUND it. The reason for
prohibiting local ALWAYS-BOUND declarations is that they are not safe
-- and (OPTIMIZE (SAFETY 0)) already has the same effect in practice.
If this is deemed too ugly, I can add support for local declarations
as well -- either as no-ops, or as no-ops outside safe code, or
whatever.
DEFGLOBAL proclaims the defined variable as both GLOBAL and
ALWAYS-BOUND, and is sort of between DEFVAR and DEFCONSTANT: the value
is evaluated both compile-time and load-time iff the name is not
already bound, in order to allow for the ALWAYS-BOUND declaration.
This is to make things like
(defglobal .lock. (make-mutex))
safe (so as not to replace the mutex with a new one when
reloading/compiling a file, etc), and to make DEFGLOBAL a mostly
drop-in replacement for DEFVAR and DEFCONSTANT where appropriate.
Users needing global equivalents of DEFPARAMETER get to roll their
own.
How does this look?
Cheers,
-- Nikodemus

> CL-USER> (my-slot-of (find-class 'test))
> ('TEST)
>
> Why value of slot "my-slot" wrapped in list?
> Maybe value of (my-slot-of (find-class 'test)) probably 'TEST, not
> ('TEST), isn't it?
(I'm not a lisp expert, this is just my understanding)
That's the way CLOS MOP is defined. See
http://www.lisp.org/mop/concepts.html#defclass, it says "Any other class
options become the value of keyword arguments with the same name. The value of
the keyword argument is the _TAIL_ of the class option.".
defclass macro expands into call to ensure-class function. And for all options
(except standard :metaclass, :documentation), CDR of the (:option value) form
is passed. I believe that it was made so it would be possible to pass list of
things as an option value.
You should modify the form like this to accomodate this behaviour:
(defclass test () ()
(:metaclass test-metaclass)
(:my-slot . test))
(note that defclass does not require quoting option values).

Community

Help

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

I agree to receive quotes, newsletters and other information from sourceforge.net and its partners regarding IT services and products. I understand that I can withdraw my consent at any time. Please refer to our Privacy Policy or Contact Us for more details