如何让比较交换接受我的变量?

How to get compare exchange to accept my variables?

我试图在我无法控制的库 API (FUSE3) 实现中的一个简单预测功能上缓解竞争条件。为此,我想在函数回调中尽早使用 std::atomic<>::compare_exchange_weak

struct fdflag
{
    // ...
    std::atomic<unsigned long long> read_seq_offset_pred;
    // ...
};

std::unordered_map<int, struct fdflag> fdflags;

static int read(const char* path, char* buffer, size_t size, off_t offset, struct fuse_file_info* fi)
{
    if (fdflags[fi->fh].read_seq_offset_pred.compare_exchange_weak(offset, offset + size)) // *
        fdflags[fi->fh].sequential_reads++;
    // ...
}

但是,gcc 不允许我这样做,抱怨(在标记为 * 的行上):

error: cannot bind non-const lvalue reference of type 'std::__atomic_base::__int_type& {aka long long unsigned int&}' to an rvalue of type 'std::__atomic_base::__int_type {aka long long unsigned int}

我试过在第一个参数上使用 const_cast<off_t&>(offset),但它给了我类似的错误消息。

如何让 compare_exchange_weak(T&, T) 接受我的参数(不增加太多开销或破坏函数签名)

您的原子存储 unsigned long long。这意味着 compare_exchange_weak 的签名是 compare_exchange_weak(unsigned long long&, unsigned long long)。由于 off_tlong int,因此您不能将其绑定到引用参数。您需要在原子变量中存储一个 off_t,将您的函数更改为采用 unsigned long long,或者将 offset 复制到函数内部的 unsigned long long 并将其传递给 compare_exchange_weak