0

Cプログラムで次の状況を考えてみましょう。関数のセットがあります。一般的なものを

 void needs_param (void * param, ...);

、いくつかのパラメータの値に依存しますparam。引数paramは関数によって計算されます。

 void compute_param (..., void * param); 

param(型、サイズ、値など) の詳細を可能な限り呼び出し元に隠したいと思います。ここで、呼び出し元は関数compute_paramおよびを使用する関数needs_paramです。needs_paramと の両方を自由に変更できる場合、これを最も効率的かつスレッドセーフに実装する方法はcompute_param?

以下の可能性を考慮し、除外しました。

a:を自由に変更できるため、これを行う 1 つの方法は、 の代わりに とその引数needs_paramを渡し、それ自体で計算させることです。ただし、計算コストが高く、他の関数への引数として何度も必要になります。gen_paramparamneeds_paramparamparam

b: 次compute_paramのように実装できます

void * compute_param (...) {
    static param_type param = ...
    return &param;
}

ただし、これはスレッドセーフではありません。使用openmpすると、呼び出しを保護する必要があります

#pragama omp critical
{
    void * param = compute_param (...)
}

これは、スレッド化されたプログラムのパフォーマンスに深刻な影響を与えます。

C: malloc/free を使用する 1 つのソリューション

void compute_param (..., void * param) {
    param = malloc (sizeof (param_type));
    ....
    *param = ...
}   

これは、割り当てられたメモリを解放することで呼び出し元に負担をかけますが、高価なヒープメモリのために非効率的です。

d:の使用alloca

void * param = alloca (param_size);
compute_param (..., param);
...
needs_param (param, ...);

param、非表示にしたい呼び出し元スペースのサイズに関する情報が必要です。

何か提案はありますか?

4

1 に答える 1

3

「不透明なポインター」と呼ばれるソリューションを使用することをお勧めします。たとえば、呼び出し元からオブジェクトを隠すために、Windows カーネルの世界で広く使用されています。

最初に のようなポインター型を定義しますtypedef void* pobject;

次に、プログラムでオブジェクトをそのように操作するだけです。のような関数の束はpobject create_object()、この手法use_object(pobject)を使用します。free_object(pobject)

オブジェクトを安全に操作できるようにするには、オブジェクト自体にミューテックスを追加します。オブジェクトのサイズを最初のメンバーとして追加して、オブジェクトの性質をすばやくチェックすることもできます (他の誰かによって操作されているかどうか)。

次に、関数で、オブジェクトを のように実際に定義しますtypedef struct { } object_int, *pobject_int。そして、それを操作するすべての関数で、不透明なポインターを からpobjectにキャストするだけpobject_intです。

確かにヒープを使用する必要がありますが、オブジェクトに関する情報を呼び出し元と共有したくない場合は、これが最適なソリューションです。

于 2013-01-16T10:49:14.797 に答える