如何在C++中以原子方式添加和获取128位数字?

alk*_*edr 4 c++ atomic

我使用Linux x86_64和clang 3.3.

这在理论上是否可行?

std::atomic<__int128_t> 不起作用(对某些函数的未定义引用).

__atomic_add_fetch 也行不通('错误:无法编译这个原子库调用').

两者std::atomic__atomic_add_fetch用64位数字的工作.

Cor*_*son 8

使用单个指令无法执行此操作,但您可以模拟它并仍然无锁.除最早的AMD64 CPU外,x64支持该CMPXCHG16B指令.通过一点点多精度数学,您可以非常轻松地完成这项工作.

我担心我不知道CMPXCHG16BGCC中的内在因素,但希望你能得到一个旋转循环的想法CMPXCHG16B.这是VC++的一些未经测试的代码:

// atomically adds 128-bit src to dst, with src getting the old dst.
void fetch_add_128b(uint64_t *dst, uint64_t* src)
{
    uint64_t srclo, srchi, olddst[2], exchlo, exchhi;

    srchi = src[0];
    srclo = src[1];
    olddst[0] = dst[0];
    olddst[1] = dst[1];

    do
    {
        exchlo = srclo + olddst[1];
        exchhi = srchi + olddst[0] + (exchlo < srclo); // add and carry
    }
    while(!_InterlockedCompareExchange128((long long*)dst,
                                          exchhi, exchlo,
                                          (long long*)olddst));

    src[0] = olddst[0];
    src[1] = olddst[1];
}
Run Code Online (Sandbox Code Playgroud)

编辑:这里有一些未经测试的代码与我可以找到的GCC内在函数有关:

// atomically adds 128-bit src to dst, returning the old dst.
__uint128_t fetch_add_128b(__uint128_t *dst, __uint128_t src)
{
    __uint128_t dstval, olddst;

    dstval = *dst;

    do
    {
        olddst = dstval;
        dstval = __sync_val_compare_and_swap(dst, dstval, dstval + src);
    }
    while(dstval != olddst);

    return dstval;
}
Run Code Online (Sandbox Code Playgroud)