2

1 つの Erlang プロセスでのみ使用される Erlang C NIF を作成しています。ポインターの配列を保持する構造体を作成したいと考えています。これは、プロセスの NIF 呼び出しの間に存在する必要があります。

私が洞察を必要としているのは、Erlang NIF 側からこのアプローチを行う適切な方法です。すべての関数の外側に構造体を記述して、すべての人がアクセスできるようにすることを考えています。NIF への 1 回の呼び出しで作成し、戻って NIF への別の呼び出しで使用すると、問題なく動作するようです。

これは、プロセスがスケジューリング スレッドに対してローカルにとどまっているため、メモリ内の構造体と基になる配列を移動する必要がないためではないかと心配しています。

関数内から erlang:memalloc を使用し、グローバルをすべて一緒に回避するべきですか、それともグローバル構造体をそのまま使用するべきですか?

すべてのデータを含む単一の配列へのポインターを返す可能性がありますか?

4

1 に答える 1

4

データを含む単一の配列へのポインターを確実に返すことができます。それを行うには、ErlNifResourceTypeを見てください。これを呼び出し元の erlang プロセスに戻すと、次の NIF 呼び出しでそれが返されます。これにより、一度に 1 つのスレッドだけがデータに対して動作することが保証されます (1 つのプロセスだけがリソースのコピーを持っていると仮定します。特にポインターが含まれている場合は共有したくないものです)。

erlang リストとしてエンコードすることもできますが、おそらく非常に非効率的です。

そうは言っても、NIF から共有メモリを使用できます。たとえば、共有データを使用して NIF として実装されたets のようなデータベースを次に示します。

共有リソースにアクセスしていることに注意してください。NIF API は、スレッドの作成スレッド固有のデータミューテックス条件、および読み取り/書き込みロックを提供します。NIF で作成されたスレッドから erlang プロセスにメッセージを送信することもできます (実行時間の長い NIF 呼び出しの場合、スケジューリングの問題を防ぐためにこれを実際に実装する方法です)。

要件を考えると、マルチスレッドや共有リソース制御をいじるよりも、おそらく ErlNifResource 型を使用する方がよいでしょう。技術的には、erlang プロセスを 1 つだけ使用している場合は、それをグローバル変数 (共有リソースと読みます) として残すことができ、有害な副作用はありません。そうは言っても、状況は変化し、誰かが複数のプロセスからコードを使用しようとしたときに、誰かの頭痛の種になりたくありません。どちらの方法を使用する場合でも、スレッドセーフであることを確認してください。

于 2013-01-22T21:07:31.190 に答える