Re: InterlockedExchange and volatile
From: Doug Harrison [MVP] (dsh_at_mvps.org)
Date: 01/11/05
- Next message: deepak: "Custom AppWizard Parsing Error"
- Previous message: Ajay Kalra: "Re: Question on Using Inheritance"
- In reply to: Pierre Couderc: "InterlockedExchange and volatile"
- Next in thread: Doug Harrison [MVP]: "Re: InterlockedExchange and volatile"
- Reply: Doug Harrison [MVP]: "Re: InterlockedExchange and volatile"
- Reply: Pierre Couderc: "Re: InterlockedExchange and volatile"
- Messages sorted by: [ date ] [ thread ]
Date: Mon, 10 Jan 2005 23:18:41 -0600
Pierre Couderc wrote:
>The documentation for InterlockedExchange says:
>
>LONG InterlockedExchange(
> LPLONG volatile Target, // value to exchange
> LONG Value // new value
>);
That declaration contains a common mistake affecting pointer typedefs,
though it's more commonly observed with const. This use of volatile modifies
Target, not what Target points to, and is thus completely useless in this
context. Making it "volatile LPLONG" doesn't help, because it's equivalent
to the above. This is not simple text substitution. There's no way for a
cv-qualifier (const or volatile) to penetrate a typedef, so if you're going
to use pointer typedefs, you need to write and use const, volatile, and
const volatile forms as necessary, e.g.
typedef LONG* LPLONG;
typedef const LONG* LPCLONG;
typedef volatile LONG* LPVLONG;
typedef const volatile LONG* LPCVLONG;
What a mess. My advice is to avoid creating pointer typedefs in your own
code.
In addition, top-level cv-qualifiers are ignored for function overloading
purposes, so the following declare the same function and thus cause an error
when compiled:
void f(int volatile x) {}
void f(int x) {}
Of course, inside the first f, x is a volatile int, but the two f's really
do try to define the exact same function for overloading purposes, and
that's illegal. However, there's no harm in merely declaring the functions
using the two forms, and it's actually useful, especially with the far more
commonly used const:
void f(int x); // In header file
void f(int const x) // Implementation
{
}
In this way, the header file isn't cluttered with top-level cv-qualified
parameters, which from the caller's perspective, would be useless detail,
but the implementation can still take advantage of them. I mean, if you like
to declare local variables const when you can, you should also like to
declare parameters const, but most people just do the former.
>But when I try to déclare my TargetValue as:
>
>volatile LONG TargetValue;
>(or LONG volatile TargetValue;)
Those two are equivalent, and they fail because passing &TargetValue to
"LPLONG volatile" or "volatile LPLONG" requires that you cast volatile away.
>I get a compile error as the declaration of InterlockedExchange in
>WINBASE.h does not conform to the documentation.
What's the declaration in your <winbase.h>?
>Is that point critical?
>What am I missing?
>(I am using MFC VC6)
I'm not sure exactly what MS was thinking when they added volatile to the
InterlockedXXX function parameters. The current Platform SDK declares the
function differently than you presented:
LONG InterlockedExchange(
LONG volatile* Target,
LONG Value
);
That fixes the mistake I was talking about earlier. However, from the
caller's perspective, this use of volatile would seem to be completely
superfluous. But then one notices the compiler provides intrinsic forms of
these functions. So, if I were to guess, I'd suppose that using volatile in
this way tells the compiler not to optimize the intrinsic forms of these
functions, especially to preserve the order and not elide anything when
there are multiple such operations in a row. I'd suppose the compiler was
considered unable to recognize the assembly code generated for the intrinsic
forms as requiring kid gloves WRT optimization. Note that this is not
required for functions that do not have intrinsic forms, including the
non-intrinsic forms of InterlockedXXX, and things like the following are
perfectly fine, assuming all threads observe the locking protocol:
lock mutex
modify non-volatile value
unlock mutex
Oh, and to fix your problem, just declare your variable as:
LONG TargetValue;
To understand when using volatile yourself may be useful, see these
messages:
http://groups.google.com/groups?selm=7hl7205u4ksejokc9ormufeo02pb9i1stu%404ax.com
http://groups.google.com/groups?selm=k7fa209epgjcn2rep0rqks2ee0f4jcitgu%404ax.com
(Any formatting glitches are the new, "improved" Google Groups Beta's
fault.)
-- Doug Harrison Microsoft MVP - Visual C++
- Next message: deepak: "Custom AppWizard Parsing Error"
- Previous message: Ajay Kalra: "Re: Question on Using Inheritance"
- In reply to: Pierre Couderc: "InterlockedExchange and volatile"
- Next in thread: Doug Harrison [MVP]: "Re: InterlockedExchange and volatile"
- Reply: Doug Harrison [MVP]: "Re: InterlockedExchange and volatile"
- Reply: Pierre Couderc: "Re: InterlockedExchange and volatile"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|