CLHS has this in the description of UNWIND-PROTECT:
> The correct way to code this is as follows:
>
> (let ((old-count *access-count*))
> (unwind-protect
> (progn (incf *access-count*)
> (perform-access))
> (setq *access-count* old-count)))
Because *ACCESS-COUNT* has stars around it, I guess it's a special
variable. Would the following simpler code then do the same thing,
or is there some race condition I overlooked?
(let ((*access-count* (1+ *access-count*)))
(perform-access))
Is the example meant to demonstrate how such a counter could be
maintained in a more complex place, like (FOO-ACCESS-COUNT *FOO*)?
Kalle Olavi Niemitalo <···@iki.fi> writes:
> CLHS has this in the description of UNWIND-PROTECT:
>
> > The correct way to code this is as follows:
> >
> > (let ((old-count *access-count*))
> > (unwind-protect
> > (progn (incf *access-count*)
> > (perform-access))
> > (setq *access-count* old-count)))
>
> Because *ACCESS-COUNT* has stars around it, I guess it's a special
> variable. Would the following simpler code then do the same thing,
> or is there some race condition I overlooked?
>
> (let ((*access-count* (1+ *access-count*)))
> (perform-access))
>
Typical multitasking implementations do not share the values of
special bindings across different tasks. So you would not have a
race-condition, but the *access-count* would only correctly reflect
the `task-local' state.
···@itasoftware.com writes:
> Typical multitasking implementations do not share the values of
> special bindings across different tasks. So you would not have a
> race-condition, but the *access-count* would only correctly reflect
> the `task-local' state.
If multitasking is involved, I don't see how the original code would
work either. If tasks A and B start running it in that order, and A
finishes its "access" first, then it restores the original value even
though B is still accessing the object.
It must be for some other reason.
In article <···············@stekt34.oulu.fi>, Kalle Olavi Niemitalo wrote:
>···@itasoftware.com writes:
>
>> Typical multitasking implementations do not share the values of
>> special bindings across different tasks. So you would not have a
>> race-condition, but the *access-count* would only correctly reflect
>> the `task-local' state.
>
>If multitasking is involved, I don't see how the original code would
>work either. If tasks A and B start running it in that order, and A
>finishes its "access" first, then it restores the original value even
>though B is still accessing the object.
>
>It must be for some other reason.
That reason would be thread-specific environments for special variable
binding, which would mean that effectively, each thread has its own
*access-count* variable which has nothing to do with any other
thread's *access-count*.
In article <···············@stekt34.oulu.fi>,
Kalle Olavi Niemitalo <···@iki.fi> wrote:
>CLHS has this in the description of UNWIND-PROTECT:
>
>> The correct way to code this is as follows:
>>
>> (let ((old-count *access-count*))
>> (unwind-protect
>> (progn (incf *access-count*)
>> (perform-access))
>> (setq *access-count* old-count)))
>
>Because *ACCESS-COUNT* has stars around it, I guess it's a special
>variable. Would the following simpler code then do the same thing,
>or is there some race condition I overlooked?
>
> (let ((*access-count* (1+ *access-count*)))
> (perform-access))
>
>Is the example meant to demonstrate how such a counter could be
>maintained in a more complex place, like (FOO-ACCESS-COUNT *FOO*)?
You must understand the example in its proper context. The purpose of that
example is to show how to use UNWIND-PROTECT properly, not to show the best
way to implement temporary updating of a variable.
If the counter were in the slot of a structure rather than a special
variable, the form of the example code would stay the same, but LET
wouldn't be available to perform the temporary binding.
--
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.