4D v16.3プリエンプティブ4Dプロセス |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
4D v16.3
プリエンプティブ4Dプロセス
プリエンプティブ4Dプロセス
OS X用 4D Developer Edition 64-bit版(Windows用は4D v16 R2以降利用可能)は プリエンプティブ 4D コード の扱いを可能にする、強力な機能を提供しています。この新機能のおかげで、コンパイルされた 4Dアプリケーションはマルチコアコンピューターの利点をすべて活かすことができ、それによって実行速度が向上し、またより多くのユーザーの接続をサポートすることができます。 プリエンプティブモードで実行された場合、プロセスはCPUに割り当てられます。プロセス管理はシステムへと委任され、マルチコアのマシン上にてシステムはプロセスをそれぞれのCPUへと個別に割り当てます。 コオペラティブモード (4D v15 R5 までは、こちらのみ使用可能) で実行された場合には、たとえマルチコアのマシン上であっても、すべてのプロセスは親アプリケーションのスレッドにより管理され、同じCPUを共有します。 結果として、プリエンプティブモードでは、アプリケーションの全体的なパフォーマンスは向上します。マルチコアのマシン上では複数のプロセス (スレッド) が真実同時実行可能であるため、パフォーマンスの向上はさらに顕著になります。 その一方で、プリエンプティブモードではそれぞれのスレッドは他から独立しており、アプリケーションによって直接管理されている訳ではないため、プリエンプティブに準拠させたいメソッドには特定の制約が課されます。それに加え、プリエンプティブ実行は特定のコンテキストでのみ使用可能です。 プリエンプティブモードの使用は、4D 64-bit版においてのみ可能です。 以下の実行コンテキストが現在サポートされています:
実行コンテキストがプリエンプティブモードをサポートし、かつメソッドが "スレッドセーフ" である場合、New process あるいは CALL WORKERコマンドあるいは "メソッドを実行" メニュー項目を使用してローンチされた新しい 4Dプロセスは、プリエンプティブスレッド内にて実行されます。 それ以外の場合で、サポートされていない実行コンテキスト (例えばリモート 4Dマシンなど) から New process あるいは CALL WORKER コマンドを呼び出した場合、プロセスは常にコオペラティブに実行されます。 注: 例えば Execute on server などのランゲージを使用したストアドプロシージャーをサーバー上で開始する事で、4Dリモートからでもプロセスをプリエンプティブに実行する事が可能です。 4Dコードは、いくつかの特定の条件に合致していた場合に限りプリエンプティブスレッド内で実行することができます。実行コードのそれぞれの部分 (コマンド、メソッド、変数など) がプリエンプティブ実行に準拠している必要性があります。プリエンプティブスレッドで実行可能な要素はスレッドセーフと呼ばれ、プリエンプティブスレッドで実行できない要素はスレッドアンセーフと呼ばれます。 注: スレッドは親プロセスメソッドをスタートとして独自に管理されているので、呼び出しチェーン全体のどこにおいてもスレッドアンセーフなコードが含まれていてはいけません。そのようなコードが含まれていた場合、プリエンプティブに実行することはできません。この点については、プロセスがプリエンプティブに実行される条件とは? の章で詳細な説明があります。 それぞれの "スレッドセーフティ" プロパティは、要素自身によります:
原則として、プリエンプティブスレッド内で実行されるコードは外部との相互作用する部分、例えばプラグインコードやインタープロセス変数などを呼び出すことはできません。しかしながら 4Dデータサーバーはプリエンプティ実行をサポートしていることから、データアクセスは可能です。 デフォルトでは、4Dはすべてのプロジェクトメソッドをコオペラティブモードで実行します。プリエンプティブモードを利用したい場合は、まず最初に、可能な限りプリエンプティブモードで開始したいメソッドをすべて明示的に宣言することから始まります。これはつまり、プリエンプティブプロセスで実行可能なメソッドであるということです。コンパイラーは、それらのメソッドが実際にスレッドセーフであるかどうかをチェックします (詳細な情報については スレッドセーフなメソッドの書き方 を参照してください)。また、必要であれば、一部のメソッドに対してプリエンプティブモードを禁止することもできます。 プリエンプティブで使用可能 ("capable") であると宣言することは、当該メソッドにプリエンプティブ実行の資格を与えますが、実行時にそのメソッドが実際にプリエンプティブモードで実行されることを保障するものではないことに留意が必要です。プロセスをプリエンプティブモードで開始することは、プロセス内の呼び出しチェーン内のすべてのメソッドの、関連プロパティを4Dが評価して初めて可能になります (より詳細な情報については、プロセスがプリエンプティブに実行される条件とは? の段落を参照してください)。 メソッドがプリエンプティブモードに則していることを宣言するためには、メソッドプロパティダイアログボックスの実行モード宣言オプションを使用する必要があります: 以下のオプションが提供されています:
注: "コンポーネントとホスト間で共有" と宣言されたコンポーネントメソッドも、ホストデータベースによってプリエンプティブプロセスで実行される場合には "capable" と宣言される必要があります。 例えば METHOD GET CODE を使用して、メソッドのコードを書き出す場合、"プリエンプティブ" プロパティは "capable"、あるいは "incapable" の値で "%attributes" コメント内に書き出されます ("indifferent" オプションを選択している場合には、このプロパティは提供されません)。METHOD GET ATTRIBUTES および METHOD SET ATTRIBUTES コマンドも、"プリエンプティブ" 属性の値 ("capable", "incapable", "indifferent") を取得、あるいは指定します。 以下の表はプリエンプティブモードの宣言オプションをまとめたものです:
リマインダー: プリエンプティブ実行はコンパイル済みモードでのみ利用可能です。 コンパイル済みモードでは、New process あるいは CALL WORKER メソッドで作成されたプロセスを開始するとき、4Dはプロセスメソッド (別名親メソッド) のプリエンプティブプロパティを読み、そのプロパティに応じてプロセスをプリエンプティブモードあるいはコオペラティブモードで実行します:
実際のスレッドセーフプロパティは呼び出しチェーンによります。"capable" と宣言されたプロパティを持つメソッドが、スレッドアンセーフなメソッドをサブレベル (どちらでも) で呼び出した場合、コンパイルエラーが返されます。呼び出しチェーン全体の中で一つでもメソッドがスレッドアンセーフであれば、それは他のすべてのメソッドをいわば "汚染" し、プリエンプティブ実行はコンパイラーによって拒否されます。プリエンプティブスレッドは、呼び出しチェーン全体がスレッドセーフであり、プロセスメソッドが "プリエンプティブプロセスで実行可能" と宣言されていた場合にのみ作成可能です。 例えば、次のプロジェクトメソッドの場合: // MyDialog プロジェクトメソッド // MyComp プロジェクトメソッド // CallDial プロジェクトメソッド // CallComp プロジェクトメソッド プリエンプティブモードでのメソッド実行は、"プリエンプティブ" プロパティや呼び出しチェーンに依存します。 以下の表は、これらの様々な状況をまとめたものです:
4Dではプロセスに対してコオペラティブ実行かプリエンプティブ実行かを識別する新機能を提供しています:
スレッドセーフであるためには、メソッドは以下のルールに従う必要があります:
注: "コンポーネントとホストデータベース間で共有"メソッドの場合、"プリエンプティブプロセスで実行可能"プロパティが選択されている必要があります。 (*) ワーカープロセスという新種のプロセスによって、プリエンプティブプロセスを含むあらゆるプロセス間ででーたの交換ができるようになります。より詳細な情報に着いてはプロセス間のメッセージ通信を参照して下さい。 "プリエンプティブプロセスで実行可能"プロパティを持つメソッドは、コンパイル時に4Dによってチェックされます。メソッドがスレッドセーフになるのを妨げる要因をコンパイラーが見つけた場合にはコンパイルエラーが生成されます。: シンボルファイル(有効化されていた場合)には、それぞれのメソッドについてのスレッドセーフの状態が含まれます: 厳密に言えば"外部"アクセスにあたるため、フォームやデバッガなどのユーザーインターフェースオブジェクトへの呼び出しは、プリエンプティブスレッドでは許可されません。 プリエンプティブスレッドからアクセス可能なユーザーインターフェースは以下のものに限られます:
4Dコマンドのうち、大多数のものがスレッドセーフです。ドキュメントの中では、コマンドプロパティエリア内の のアイコンがコマンドがスレッドセーフであることを表しています。ランゲージリファレンスマニュアル内にてスレッドセーフであるコマンドの一覧を取得する事ができます。 また Command name を使用するとそれぞれのコマンドについてスレッドセーフかどうかのプロパティを取得する事ができます(以下参照)。 メソッドがトリガーを呼び出す事のできるコマンドを使用している場合、4Dコンパイラはメソッドがスレッドセーフであるかどうかをチェックするために、トリガーがスレッドセーフかどうかを評価します: SAVE RECORD([Table_1]) //Table_1をトリガーし、存在すれば、スレッドセーフでなければならない 以下は、コンパイル時にトリガーがスレッドセーフであるかどうかをチェックされるコマンドの一覧です:
テーブルが動的に渡された場合、コンパイラはどのトリガーを評価すべきなのかが分からない場合があります。以下はそのような状況の一例です: DEFAULT TABLE([Table_1]) この場合、すべてのトリガーが評価されます。 少なくとも一つのトリガー内でスレッドセーフでないコマンドが検出された場合、グループ全体がチェックに失敗し、メソッドはスレッドアンセーフと宣言されます。 ON ERR CALLコマンドによって実装されたエラーキャッチメソッドは、プリエンプティブプロセスから呼び出される可能性が高いのであれば、スレッドセーフでなければなりません。このような状況を管理するため、コンパイラはコンパイル時にON ERR CALLコマンドに渡されたエラーキャッチプロジェクトメソッドのスレッドセーフプロパティをチェックするようになり、メソッドがプリエンプティブ実行に適応していない場合には適切なエラーを返します。 このチェックはメソッド名が定数として渡された場合にのみ可能であり、以下に示す様な、計算された値の場合にはチェックされないという点に注意して下さい: ON ERR CALL("myErrMethod1") //コンパイラによってチェックされる これに加え、4D v15 R5以降、エラーキャッチもロジェクとメソッドがランタイムで呼び出す事ができない場合(スレッドセーフに関する問題がある、あるいは"メソッドが見つかりません"などの理由の場合)、新しいエラー-10532 "'methodName'というエラーハンドルメソッドを呼び出す事ができません"エラーが生成されます。 プロセスは、両プロセスがともにコオペラティブであった場合に限り、ポインターを参照して他のプロセス変数の値へアクセスすることができます。それ以外の場合、4Dはエラーを生成します。プリエンプティブプロセスにおいては、4Dコードがインタープロセス変数の値をポインター経由で参照しようとした場合、エラーが生成されます。 以下のメソッドでそのような例を考えます: Method1: myVar:=42 Method2: $value:=$1-> Method1、あるいはMethod2を実行するプロセスのどちらか一つがプリエンプティブであった場合、"$value:=$1->"という式は実行エラーを生成します。 DocRef 参照番号 (開かれたドキュメントの参照番号で次のコマンドに使用、または戻り値として返されます: Open document, Create document, Append document, CLOSE DOCUMENT, RECEIVE PACKET, SEND PACKET) の使用は次のコンテキストに限られます:
DocRef 参照についての詳細は DocRef: ドキュメント参照番号 を参照ください。
参照
|
プロパティ
プロダクト: 4D
履歴
初出: 4D v15 R5 ARTICLE USAGE
ランゲージリファレンス ( 4D v16.1) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||