一部のエンジンは内部データ構造へのアクセスを同期しないため、DWScriptがスクリプト内のスレッドを使用できるかどうかを知りたいです。
2 に答える
Arnaudは重要なポイントを与えました:
- 各コンパイラインスタンスは、一度に1つのスレッドからのみ呼び出すことができます。複数のスレッドで同時に複数のコンパイラインスタンスを呼び出すことができ、一度に1つのスレッドのみが使用する場合は、特定のコンパイラインスタンスを複数のスレッドから使用できます。
- コンパイルされた各プログラムは複数の実行を持つことができ、各実行は独自のスレッドで実行できます。また、特定の実行は、一度に1つのスレッドのみが使用する場合、複数のスレッドで使用できます。
- 各実行には変数用の独自のスペースがあり、独自のスタック、オブジェクトインスタンスはヒープ上にあり、技術的には実行間で共有できます。そのためのロックメカニズムはありませんが、独自に作成することもできます。
- スクリプトエンジンは、公開されているクラスまたは関数を使用する場合(TdwsUnit、RTTIなどを介して)、同期またはロックを実行しないため、スレッドでスクリプト実行を実行する場合は、スレッドセーフなもののみを公開するようにしてください(特にRTLとVCLの多くはそもそもスレッドセーフではないため、RTTIの場合は注意が必要です)
スクリプトの複数の実行を実行することは、Delphiで複数のスレッドを使用することに似ていますが、新しい実行ごとに、独自のスタック(Delphiスレッドなど)だけでなく、独自の可変スペースもあります(Delphiでは、「スレッド」がある場合と少し似ています。 var "どこでも)。また、DWScriptの実行は独自のスレッドにある必要はなく、スレッド間で移動したり、ポーリングして少数のスレッドで使用したりできます(唯一の制限は、各実行が一度に1つのスレッドでのみ使用されることです。上記の通り)。
したがって、スクリプト関数でスレッド(および対応する実行)を生成する関数を公開することを妨げるものは何もありませんが、実行間の通信は共有変数を介して行われることはありません(Delphiで行うように誘惑される可能性があります)が、独自の公開された関数(または外部変数)、戻り値(「評価」アプローチを使用、単体テストを参照)、「共有」オブジェクトインスタンス、または「グローバル変数」を実行します。
「グローバル変数」とは、dwsGlobalVarsFunctions.pasで定義されている関数を意味し、実行間のデータ交換に使用できます。それらをアクティブにするには、プロジェクトのどこかに「usesdwsGlobalVarsFunctions」を配置するだけです。
これらは、Read / WriteGlobalVar関数のセットを公開します。これにより、同じDelphiプロセス内で実行されるすべてのスクリプト実行にわたって名前付きバリアントを保存および取得できます。これらの読み取りおよび書き込みは、スレッド化の観点から「アトミック」です。
DWSドキュメントを開く必要すらありませんでした。:)
エリックによるこのStackOverflowの回答を見てください:
たとえば、[DWS]は、単一のコンパイル済みスクリプトを複数のスレッドセーフで実行できるようになりましたが、古いコードベースは、コンパイル済みスクリプトを一度に1つのスレッドでしか実行できないという制限に基づいて構築されています。
要するに:
- DWSコンパイラはスレッドセーフではありません。1つのスレッド内に実行スタックを作成する必要があります(コンパイラインスタンスを共有することはできません。コンパイラインスタンスごとに1つのスレッドが必要です)。
- スレッドごとに1つの実行インスタンスを使用する場合、DWSの実行はスレッドセーフです。同じコンパイル済みスクリプトを複数のスレッドで実行できます。
- スレッド間の通信はAFAIKでは利用できませんが、同期が必要な場合はDelphiコードを使用できます。
もちろん、ここにDWSのスレッドセーフに関する公式ドキュメントページがあります。
これで、特定のIdwsProgramに対して必要な数のプログラムを実行できます。各実行は、ヒープとスタックにのみメモリを使用し、コンパイルされた式ツリーは共有されます。新しいインターフェイスは両方とも、参照カウントされたメモリ管理を使用します。