我正在编写一个库,其中另一种语言的连接库只能理解C.我需要与std::shared_ptr
类似的东西,其中所有权是共享的。在我的情况下,手动引用计数就可以了。
C11 supports atomic operations。我一直试图找到一个如何正确执行此操作的示例,但我能够找到的每个示例都与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
的含义是什么,我应该用什么来引用计数?这有关系吗?
答案 0 :(得分: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操作,但是对两者都使用完全障碍也是可以的。