Why this question is invalid
C++11 atomics require you to use C++11 atomic types for atomic operations. You can step outside the standard by casting from non-atomic to atomic types, but this is not portable code, even if it often works. It's not even valid from an entirely C++ code, let alone a mixture of C and C++.
Because of this limitation, you will not be able to write a C++ atomics library with an interface to C, because you cannot declare C++11 atomic types in C code.
Hans Boehm, one of the foremost authorities on programming language concurrency features, has a proposal for C++0y titled N4013: Atomic operations on non-atomic data that explains some of the issues here.
A different way to solve the problem
You can solve this entirely within C, which is the safest and most portable solution.
The most common way to do atomics in C and C++ prior to the introduction of native language types in C11 and C++11 is with compiler intrinsics. There are two variants of these:
Both of these are supported by GCC, Clang and Intel compilers as well as other compilers (IBM for sure, Cray mostly but with at least one bug, and probably PGI). I don't use Windows but I know MSVC has some sort of compiler intrinsics for atomics.
In addition, there are at least two different open-source implementations of C atomics with permissive licenses:
Additionally, OpenMP 3+ gives you the ability to use atomics from C89 code, but I don't know if MSVC supports it sufficiently.
Finally, C11 atomics will solve your problem beautifully in an entirely ISO standard way. However, compiler support is rather limited right now. I have used these features with GCC 5+ and late-model Clang, and perhaps Intel 16, but I do not expect MSVC to ever support them.
Code
I removed volatile
from the value, since it does nothing. The extern "C"
is not required except to turn off C++ name-mangling, as none of the implementations use C++. Because you didn't specify a memory ordering requirement, I assume relaxed (unordered) atomics are sufficient.
__sync version
extern "C"
{
int do_atomic_int_add(volatile int* i, int v)
{
//return (*i + v);
return __sync_add_and_fetch(i,v);
}
}
__atomic version
extern "C"
{
int do_atomic_int_add(volatile int* i, int v)
{
//return (*i + v);
return __atomic_add_fetch(i,v, __ATOMIC_RELAXED);
}
}
OpenMP version
extern "C"
{
int do_atomic_int_add(volatile int* i, int v)
{
int r;
#pragma omp atomic update
{ r = (*i + v); }
return r;
}
}