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...
    }
}

オーダー/バリア セマンティクスに関しては、retain は取得操作であり、release は解放操作である必要がありますが、両方にフル バリアを使用することも問題ありません。

于 2013-09-19T17:40:54.440 に答える