2

我正在编写一个库,其中另一种语言的连接库只能理解 C。我需要类似于std::shared_ptr共享所有权的东西。在我的情况下,手动引用计数就可以了。

C11 支持原子操作。我一直在尝试找到一个如何正确执行此操作的示例,但是我能够找到的每个示例都与 C++11 有关,它具有运算符重载。

基本上我想做的是这样的:

typedef struct {
    union {
        int integer;
        // ...
        char* cstring;
        void* ptr;
    };
    enum {
        Undefined,
        Integer,
        String,
        // ...
    } type;
    int* refcount;
} value;

void value_retain(value v) {
    ++(*v.refcount);
}

void value_release(value v) {
    if(--(*v.refcount) == 0) {
        // free memory, depending on type...
    }
}

我假设我需要更改int*atomic_int*. 函数atomic_fetch_sub表示它返回“先前保存的值是 obj 指向的原子对象。”。这让我相信我的函数看起来像这样:

void value_retain(value v) {
    atomic_fetch_add(v.refcount, 1);
}

void value_release(value v) {
    if(atomic_fetch_sub(v.refcount, 1) == 1) {
        // free memory, depending on type...
    }
}

这甚至正确吗?我担心的是atomic_fetch_sub返回的值什么,而不是值什么。

还有什么memory_order意思,我应该用什么来进行引用计数?有关系吗?

4

1 回答 1

4

我认为您的设计是正确的,除了int* refcount;指针的类型和错误使用。现在你没有任何东西可以指向它,所以你将通过将(不确定的)指针值传递给原子操作来调用未定义的行为。我不明白你为什么要使用指针。类型应该是:

int refcount;

并且代码应该是:

void value_retain(value v) {
    atomic_fetch_add(&v.refcount, 1);
}

void value_release(value v) {
    if(atomic_fetch_sub(&v.refcount, 1) == 1) {
        // free memory, depending on type...
    }
}

至于 order/barrier 语义,retain 应该是获取操作,release 应该是 release 操作,但是两者都使用完整的屏障也是可以的。

于 2013-09-19T17:40:54.440 回答