保護されている操作は、ガード済み操作と呼ばれます。ガード済み操作は、非常に重要なため、相互排他を強制する必要があると考えられています。 ガード済みオブジェクトは、少なくとも 1 つのガード済み操作を所有するオブジェクトです。
ガード済みオブジェクトを実装する 1 つの方法は、mutex を指定して、ガード済みであると明示的に設定されるすべての操作で、その開始時に mutex をロックして、終了時に解除することです。
RiCMonitor メンバーが、ガード済みオブジェクトの構造に追加されます。 例:
typedef struct A A;
struct A {
RiCMonitor ric_monitor;
/* other members of A */
};
RiCMonitor は、IBM® Rational® Rhapsody® フレームワークに定義されるモニター・タイプです。
ric_monitor サブオブジェクトは、ガード済みとタグを付けられているオブジェクトの操作にのみ使用されます。 操作には、CG::Operation::Concurrency プロパティーを使用してガード済みというタグを付けることができます。
ガード済み操作は、保護の役割を持つラッパー操作内で保護されます。 ガード済み操作は、プライベート操作として次のように生成されます。
例えば、オブジェクト B のガード済み操作 increase() 用に 2 つの関数が生成されます。
ラッパー操作の宣言は、オブジェクトの宣言ファイルに生成されます。
int B_increase(B* const me, int i);
ラッパー操作 increase() は、 ric_monitor オブジェクトに対するロックを取得し、ガード済み操作を呼び出し、最後にそのロックを解除します。
int B_increase(B* const me, int i) {
int wrapper_return_value;
RIC_OPERATION_LOCK(&me->ric_monitor);
wrapper_return_value = B_increase_guarded(me, i);
RIC_OPERATION_FREE(&me->ric_monitor);
return wrapper_return_value;
}
一度、ラッパー関数がロックを取得すると、ガード済み操作は保護されて、ロックが解除されるまで他のオブジェクトにアクセスされることなく、その重要な操作を実行できます。
static int B_increase_guarded(B* const me, int i) {
{
/*#[ operation increase(int) */
return i++;
/*#]*/
}
}
同様に、ガード済みオブジェクトのための cleanup 操作が、ラッパー操作とクリーンアップを実行するガード済み操作に生成されます。 例えば、ガード済みオブジェクト B のクリーンアップは、まず、B をロックして、次に実際のクリーンアップを行う cleanup_guarded() を呼び出します。
void B_Cleanup(B* const me) {
RIC_OPERATION_LOCK(&me->ric_monitor);
B_Cleanup_guarded(me);
}
void B_Cleanup_guarded(B* const me) {
RiCMonitor_cleanup(&me->ric_monitor);
}