Hi,
Sorry for this confusion - I forgot about this issue - been a while since I used VC6.
The prototype but not the behaviour of InterlockedCompareExchange changed between VC 6 and 7. Semantically, tte correct code is as per the patch I submitted - values of the comparand and exchangand should be passed by value not reference. The VC6 prototype simply assumed "void*" was a good alias for "32-bit value" - VC7 corrected this.
To get it to compile under VC6 the correct (extremely ugly) change would be simply:
while (InterlockedCompareExchange((void **)&g_uModuleInitializing, (void*)1, (void *) 0));
but this would of course still break VC7 compiles.
To get code that will compiler under either it's probably better to simply use InterlockedIncrement/Decrement for this stuff.
The implementation of start_initializing/done_initializing should compile on both but may generate warnings on VC6 because VC6's prototypes don't use "volatile".
static volatile long g_uModuleInitializing = 0;
static void start_initializing()
{
while (InterlockedIncrement(&g_uModuleInitializing) != 1) {
InterlockedDecrement(&g_uModuleInitializing);
}
}
static void done_initializing()
{
InterlockedDecrement(&g_uModuleInitializing);
}
You can also use:
#if _MSC_VER >= 1300
while (InterlockedCompareExchange(&g_uModuleInitializing, 1, 0));
#else
while (InterlockedCompareExchange(((void **)&g_uModuleInitializing, (void*)1, (void *) 0));
#endif
_MSC_VER is defined as 1200 for VC6 and 1300 for VC7.
But this isn't necessarily reliable since it's OK to use VC6 (_MSC_VER == 1200) with the VC7 header files (which are available separately as the platform SDK) - in fact I think this is what I did when testing this coding.
Cheers,
Tim
--
IBM Tivoli Access Manager Development
Gold Coast Development Lab, Australia
+61-7-5552-4001 phone
+61-7-5571-0420 fax
| Adrian Dick <[EMAIL PROTECTED]>
04/11/05 11:58 PM
|
|
Rob,
As you comment below, the code in CVS does not exactly match the original
patch provided, due to the apparent differences in API between MS VC++
versions.
>From <MS VC++ 6.0 install>\Include\WINBASE.H
PVOID
WINAPI
InterlockedCompareExchange (
PVOID *Destination,
PVOID Exchange,
PVOID Comperand
);
I initially tried using the version provided in the original patch (which
matches your suggested usage), but received compilation errors, basically
the reverse of those you are seeing.
Adrian
_______________________________________
Adrian Dick ([EMAIL PROTECTED])
"Rob Lievaart" <[EMAIL PROTECTED]> wrote on 11/04/2005 14:22:45:
> Hi Adrian,
>
> There are two things here, one is the signature of the function,
> and one is the actual parameter values.
>
> I can imagine something about the different compiler versions
> being more or less picky about signatures which types can and cannot be
> converted to each other, but I find it hard to believe that
> Microsoft changed the actual system call. According to the
> documentation parameter 2 and 3 need to be the values to be
> compared and exchanged, but instead of these values, _pointers_
> to these values are passed.
>
> As far as I can see, the current function passes two pointers instead
> of a '1' and a '0' for exchange and comparand. The result is that
> g_uModuleInitializing is never equal to the comparand, so it is never
> actually set to any other value then 0. The function will return the
> initial 0, so it will continue thinking it has the lock, but without
> actually setting the flag.
>
> I guess, the chance of multiple threads actually trying to initialize at
>
> the same time, is pretty low, so it will seem to work, but it does not
> provide any protection this way.
>
> > This appears to be a problem between different versions of MS VC++.
> >
> > I applied this fix, as provided in
> > http://issues.apache.org/jira/browse/AXISCPP-557.
>
> Ehh, the patch you refer to in this issue shows the following code:
>
> + static void start_initializing()
> + {
> + while (InterlockedCompareExchange(&g_uModuleInitializing, 1, 0));
> + }
>
> However the version in CVS has:
>
> static void start_initializing()
> {
> long exchange = 1;
> long comperand = 0;
> while (InterlockedCompareExchange(((void **)&g_uModuleInitializing),
> void*)&exchange, (void *) &comperand)));
> }
>
> Apart from the void * casts, the first one passes the values 1 and 0,
> and the
> second one passes the address of 2 variables that contain 1 and zero.
> The version in CVS definately does not match de documentation from
> Microsoft.
>
> I currently don't have VC6.0 installed to check out, what the problem
> is. But my
> guess is that the version in the original patch is correct.
> (I used the original version on VC7.1 and it compiles)
>
> Do you remember what problems VC6.0 had with the original version?
>
>
> Kind regards,
>
>
>
> Rob.
>
>
>
