Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

InterlockedIncrement64 with managed C++

I'm porting code written under Visual Studio 2012 to compile with Visual Studio 2015. The code builds OK with Windows 2012.

I have an issue with some code that calls InterlockedIncrement64. It builds OK for an x64 target, but fails where the target is Win32 and the calling code is managed (i.e. compiled with /clr), yielding:

error C3861: 'InterlockedIncrement64': identifier not found

Looking in winnt.h, it seems that InterlockedIncrement64 is undefined when the target is Win32 and _MANAGED is defined.

I can rearrange the code such that InterlockedIncrement64 isn't called for managed code, but I'm still curious to know why this change in behavior has come with Visual Studio 2015.

like image 736
Mark Short Avatar asked May 31 '16 14:05

Mark Short


1 Answers

As the name implies, InterlockedIncrement64 is an atomic increment operation for a LONGLONG, and it needs memory to be 64 bit aligned.

Given that you can't set memory alignment in managed code and it may be used for managed class members then this limitation makes sense (to me): "...otherwise, this function will behave unpredictably on multiprocessor x86 systems and any non-x86 systems.". Think about this:

::InterlockedIncrement64(&_memberVariable);

If _memberVariable is allocated in managed world, then it won't be 64-bit aligned (though it may happen by chance), and this code will always fail for Win32. It's simpler to remove this function when _MANAGED is defined.

Workaround: check #ifdef _MANAGED and call Interlocked::Increment instead, or drop atomicity (!) but include a memory barrier after increment.

like image 60
Adriano Repetti Avatar answered Nov 18 '22 18:11

Adriano Repetti