#include <stdio.h> #include <string.h> #include "GlueLogicAPI.h" void main( argc, argv ) int argc; char **argv; { char line[1024], *p, *q; GlueLogicParseArgs( argc, argv ); GlueLogicConnect( "GlueC#", NULL, NULL ); printf( "Agent: [%s]\nServer: [%s]\nAnchor: [%s]\n\n", GlueLogicAgent, GlueLogicServer, GlueLogicAnchor ); sprintf( line, "!AddInformTo %s.a %s", GlueLogicAnchor, GlueLogicAgent ); GlueLogicAccess(line, 1024, line, NULL); sprintf( line, "!AddInformTo %s.bb %s", GlueLogicAnchor, GlueLogicAgent ); GlueLogicAccess(line, 1024, line, NULL); sprintf( line, "!AddInformTo %s.zzz %s", GlueLogicAnchor, GlueLogicAgent ); GlueLogicAccess(line, 1024, line, NULL); while (1) { GlueLogicEnqueueMessage(); if ( ! GlueLogicMessageLines() ) { GlueLogicWaitForMessage(); GlueLogicEnqueueMessage(); } if ( GlueLogicEndOfMessage() ) { break; } if ( GlueLogicGetMessage(line,1024) == NULL ) { continue; } if ( strncmp( line, "Changed ", 8 ) ) { continue; } if ( q = strchr( (p = line+8), ' ' ) ) ) { *q = '\0'; } if ( strncmp( p, GlueLogicAnchor, strlen(GlueLogicAnchor) ) ) { continue; } p += strlen( GlueLogicAnchor ); if ( ! strcmp( p, ".a" ) ) { ProcessEventA(); } else if ( ! strcmp( p, ".bb" ) ) { ProcessEventBB(); } else if ( ! strcmp( p, ".zzz" ) ) { break; } } sprintf( line, "!DelInformTo %s.a %s", GlueLogicAnchor, GlueLogicAgent ); GlueLogicAccess(line, 1024, line, NULL); sprintf( line, "!DelInformTo %s.bb %s", GlueLogicAnchor, GlueLogicAgent ); GlueLogicAccess(line, 1024, line, NULL); sprintf( line, "!DelInformTo %s.zzz %s", GlueLogicAnchor, GlueLogicAgent ); GlueLogicAccess(line, 1024, line, NULL); GlueLogicDisconnect(); exit(0); }このプログラムは三つの部分から構成されており、 それぞれ初期化部, イベントループ, 終結部とでも呼ぶべき機能を果たしている。
その後に GlueLogicConnect 関数によって
サーバと通信路を開設するが、この時に与えられる引数は
通信路開設時にはもっとも優先度の低い情報源として利用される。
すなわち、これらの引数よりは環境変数の指定の方が優先され、
さらにそれらよりは GlueLogicAgent, GlueLogicAnchor,
GlueLogicServer の
各文字配列の値の方が優先される。
このため、 GlueLogicParseArgs 関数が既に実行されておれば、
コマンドライン引数として指定された値が最優先で使われることになる。
初期化の最後としてこのエージェントが監視しようとする名前について、 変更通知メッセージの要求登録を行なう。
エンドレス・ループの先頭では、 GlueLogicEnqueueMessage 関数を用いて、 サーバからの変更通知、もしくは標準入力からの入力行が到着しておれば、 それらを対応する待ち行列の最後尾に入れる。 その後、 GlueLogicMessageLines 関数を用いて変更通知メッセージの待ち行列の長さを確認し、 もしも一つもメッセージが入っていない場合には GlueLogicWaitForMessage 関数を呼び出す。 この関数は変更通知メッセージまたは標準入力からの入力行のどちらか一方が確認されるまで待ち合わせる。
もし万一、サーバが異常終了していた場合には、 GlueLogicEndOfMessage は真の論理値を返す。 この場合には必ずイベントループから抜け出すようにしておかなければならない。 なお、サーバの異常終了によって通信路が閉鎖されてしまった後では、 どの API も何もしないようになるので、 以降の処理で特に場合分けを行なう必要は無い。
次に、 GlueLogicGetMessage 関数を使って 変更通知メッセージの待ち行列の先頭の要素を読み出す。 GlueLogicWaitForMessage 関数から戻って来る原因となったイベントが 標準入力からの入力であった場合など、 待ち行列が空になっている場合には、 GlueLogicGetMessage 関数の戻り値は NULL になる。 この場合には以下の処理は無駄であるので、次にイベントの発生を待つ。
以降の連続する if 文によって行なわれる処理が、 値の変更があった事が通知された名前毎に、 対応する処理関数を呼び出す部分である。 これらの関数の中では、必要に応じて、新しい値の取得、 対応する内部処理、 GlueLogic に対するデータの書き込みが行なわれる。
この例では、 イベントとしてサーバからの通知メッセージの到着のみを対象としているが、 GlueLogicEnqueueMessage 関数は 原則として標準入力からの入力行の到着も通知メッセージの到着と同等に扱う。 このため、どちらか一方だけを問題にしたい場合には、 この例のように他方のイベントの発生を適切に無視するように注意しなければならない。
自分が変更要求を出していた名前の全てに対して、 忘れずに必ず要求登録を抹消しなければならない。